• Educational Codeforces Round 47 (Rated for Div. 2)G. Allowed Letters 网络流


    题意:给你一个字符串,和每个位置可能的字符(没有就可以放任意字符)要求一个排列使得每个位置的字符在可能的字符中,求字典序最小的那个
    题解:很容易判断有没有解,建6个点表示从a-f,和源点连边,容量为原串字符出现次数,再建64个点表示给定的位置的每一个状态,和汇点连边,容量为出现次数,如果a-f某个字符在状态中出现过,再把a-f和状态连边,容量inf,但是这只能求可行解,并不是字典序最小,
    我们枚举每个位置该放哪个字符(a-f),假设该位置是pos,枚举的字符是x,该位置可能字符的状态是st,现在流量是s->x->st->t,如果这条路上最小流量不是0,我们把这条路往回流1然后,把容量缩小1,判断后面的字符是不是可行,如果可行,那么我们就在该位置放x,(从小到大枚举,贪心的放),
    现在有一个问题就是虽然s->x,st->t可能有流量,但是x到st不一定流量,所以我们枚举x到达的每一个状态,然后回流1,再枚举st对应的每个字符,回流1,最后统一增广
    还好这题图是个二分图,不然回流可能写死人
    虽然我写了当前弧优化,还是没用,不加编译优化会t!!!

    #pragma comment(linker, "/stack:200000000")
    #pragma GCC optimize("Ofast,no-stack-protector")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    
    using namespace std;
    
    const double g=10.0,eps=1e-12;
    const int N=73+10,maxn=1500+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
    
    struct edge{
        int to,Next,c,cc;
    }e[maxn];
    int s,t,cnt,head[N],cur[N];
    vi v[N],rev[N];
    void init()
    {
        cnt=0;
        memset(head,-1,sizeof head);
    }
    void add(int u,int v,int c)
    {
        e[cnt].to=v;
        e[cnt].c=c;
        e[cnt].cc=c;
        e[cnt].Next=head[u];
        head[u]=cnt++;
        e[cnt].to=u;
        e[cnt].c=0;
        e[cnt].cc=0;
        e[cnt].Next=head[v];
        head[v]=cnt++;
    }
    int dis[N];
    bool bfs()
    {
        queue<int>q;
        memset(dis,-1,sizeof dis);
        dis[s]=1;
        q.push(s);
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=head[x];~i;i=e[i].Next)
            {
                int y=e[i].to;
                if(dis[y]==-1&&e[i].c>0)
                {
                    dis[y]=dis[x]+1;
                    q.push(y);
                }
            }
        }
        return dis[t]!=-1;
    }
    int dfs(int u,int mx)
    {
        if(u==t)return mx;
        int f;
        for(int &i=cur[u];~i;i=e[i].Next)
        {
            int x=e[i].to;
            if(dis[x]==dis[u]+1&&e[i].c>0&&(f=dfs(x,min(mx,e[i].c))))
            {
                e[i].c-=f;
                e[i^1].c+=f;
                return f;
            }
        }
        return 0;
    }
    int maxflow()
    {
        int ans=0,f;
        while(bfs())
        {
            for(int i=0;i<=t;i++)cur[i]=head[i];
            while((f=dfs(s,inf)))ans+=f;
        }
        return ans;
    }
    void calcelflow(int be,int en)
    {
    
    }
    char c[100010],cc[10];
    int mask[100010],a[10],num[100];
    int id[100][100];
    int main()
    {
        scanf("%s",c);
        int n=strlen(c),m;
        for(int i=0;i<n;i++)a[c[i]-'a']++;
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            int id;
            scanf("%d%s",&id,cc);id--;
            int len=strlen(cc);
            for(int j=0;j<len;j++)mask[id]|=(1<<(cc[j]-'a'));
            if(!mask[id])mask[id]=(1<<6)-1;
            num[mask[id]]++;
        }
        for(int i=0;i<n;i++)
            if(!mask[i])
                num[mask[i]=(1<<6)-1]++;
        s=6+(1<<6),t=6+(1<<6)+1;
        init();
        for(int i=0;i<6;i++)id[s][i]=cnt,add(s,i,a[i]);
        for(int i=0;i<(1<<6);i++)id[i+6][t]=cnt,add(i+6,t,num[i]);
        for(int i=0;i<(1<<6);i++)
            for(int j=0;j<6;j++)
                if((i>>j)&1)
                    v[j].pb(i),rev[i].pb(j),
                    id[j][i+6]=cnt,add(j,i+6,inf);
        int ans=maxflow();
        for(int i=0;i<n;i++)
        {
            bool ok=1;
            for(int j=0;j<6;j++)
            {
                if(!((mask[i]>>j)&1))continue;
                if(e[id[s][j]+1].c==0||e[id[mask[i]+6][t]+1].c==0)continue;
                for(int k=0;k<rev[mask[i]].size();k++)
                {
                    int x=rev[mask[i]][k];
                    if(e[id[x][mask[i]+6]+1].c!=0&&e[id[s][x]+1].c!=0)
                    {
                        int mi=min(e[id[x][mask[i]+6]+1].c,min(e[id[s][x]+1].c,e[id[mask[i]+6][t]+1].c));
                        e[id[s][x]+1].c-=1;
                        e[id[x][mask[i]+6]+1].c-=1;
                        e[id[mask[i]+6][t]+1].c-=1;
                        e[id[s][x]].c+=1;
                        e[id[x][mask[i]+6]].c+=1;
                        e[id[mask[i]+6][t]].c+=1;
                        ans-=1;
                        break;
                    }
                }
                for(int k=0;k<v[j].size();k++)
                {
                    int x=v[j][k];
                    if(e[id[j][x+6]+1].c!=0&&e[id[x+6][t]+1].c!=0)
                    {
                        int mi=min(e[id[s][j]+1].c,min(e[id[j][x+6]+1].c,e[id[x+6][t]+1].c));
                        e[id[s][j]+1].c-=1;
                        e[id[j][x+6]+1].c-=1;
                        e[id[x+6][t]+1].c-=1;
                        e[id[s][j]].c+=1;
                        e[id[j][x+6]].c+=1;
                        e[id[x+6][t]].c+=1;
                        ans-=1;
                        break;
                    }
                }
                if(e[id[s][j]].c==0||e[id[j][mask[i]+6]].c==0||e[id[mask[i]+6][t]].c==0)continue;
                e[id[s][j]].c--,e[id[j][mask[i]+6]].c--,e[id[mask[i]+6][t]].c--;
                ans+=maxflow();
                if(ans==n-i-1)
                {
                    c[i]=j+'a';
                    ok=0;
                    break;
                }
                else e[id[s][j]].c++,e[id[j][mask[i]+6]].c++,e[id[mask[i]+6][t]].c++,ans+=maxflow();
            }
            if(ok)return 0*puts("Impossible");
        }
        printf("%s
    ",c);
        return 0;
    }
    /***********************
    bedefead
    5
    2 e
    1 dc
    5 b
    7 ef
    6 ef
    ***********************/
    
  • 相关阅读:
    截图片
    C#根据字节数截取字符串
    学习ObjectiveC: 入门教程
    [原]32位libusb
    [转]vim下鼠标右键无法复制的解决
    [原]c语言问号表达式
    [转]Linux下的帧缓冲lcd应用编程及Framebuffer驱动程序模型
    [转] android移植详解
    [转]Linux 串口编程
    curl 使用代理
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9339062.html
Copyright © 2020-2023  润新知