POJ1087 A Plug for UNIX(map+dinic最大流)

来源:互联网 发布:java并发编程好的书籍 编辑:程序博客网 时间:2024/05/29 10:01

链接:http://poj.org/problem?id=1087
这题题意读懂了以后就好做了。
题意:
输入n,后面是n个插座。输入m,后面是m个电器,以及他们使用的插座名字
输入k,后面是k种转换器,表示前面的那个插座可以通过转换器转换到后面的插座。
问:最少有几个电器没有插座。
很容易想明白,这是一个最大流问题。建立一个源点和汇点,源点到每种插座的权值是这种插座被几个电器使用。只有最开始输入的n种插座能向汇点连边,因为全部插座就是一开始的n种,而且每种插座到汇点的权值是这种插座的数量。
k个转换器就是在插座之间连边就行了,权值是m,因为可以无限转换。然后就是一个最大流模型,dinic解决。这题的麻烦之处在于,输入都是用字符串操作,所以我用了一个map来记录编号,操作编号即可。答案是最少有几个电器没有插座,答案就是:总电器数-最多有几个电器有插座。

#include<cstdio>#include<cstring>#include<string>#include<queue>#include<map>#include<iostream>#include<vector>#include<cstdlib>#include<cmath>#include<stack>#include<cctype>#include<set>#include<algorithm>using namespace std;const int INF=1e9+7;typedef pair<int,int> pii;typedef long long ll;map<string,int> id;int n,m,idcnt,st,ed;int a[410],tot[410],pic[410][410],d[410],cnt[410];//a数组是记录输入的n个插座的编号//tot数组记录有几个电器用到了这个插座//d数组在BFS的时候记录距离//cnt数组记录在输入的n个插座中每种分别有几个int ID(string a){//记录编号    if(id.count(a))return id[a];    return id[a]=++idcnt;}void build(){    st=0;ed=idcnt+1;    for(int i=1;i<=idcnt;i++){        pic[st][i]=tot[i];    }    for(int i=1;i<=n;i++){        pic[a[i]][ed]=cnt[a[i]];    }}bool BFS(){    queue<int> Q;    memset(d,-1,sizeof d);    d[st]=0;Q.push(st);    while(!Q.empty()){        int s=Q.front();Q.pop();        for(int i=1;i<=ed;i++){            if(pic[s][i]>0&&d[i]<0){                d[i]=d[s]+1;Q.push(i);            }        }    }    return d[ed]>0;}int DFS(int s,int t,int flow){    if(s==t||flow==0)return flow;    int ans=0;    for(int i=1;i<=ed;i++){        if(d[i]==d[s]+1&&pic[s][i]>0){            int ff=DFS(i,t,min(flow,pic[s][i]));            if(ff>0){                pic[s][i]-=ff;                pic[i][s]+=ff;                ans+=ff;                flow-=ff;                if(!flow)break;            }        }    }    if(!ans)d[s]=-1;    return ans;}void dinic(){    int ans=0;    while(BFS()){        ans+=DFS(st,ed,INF);    }    printf("%d\n",m-ans);//答案是m-ans}int main(){//    freopen("D://input.txt","r",stdin);    while(scanf("%d",&n)!=EOF){        idcnt=0;id.clear();        memset(a,0,sizeof a);        memset(cnt,0,sizeof cnt);        memset(pic,0,sizeof pic);        memset(tot,0,sizeof tot);        for(int i=1;i<=n;i++){            string x;cin>>x;            int now=ID(x);            a[i]=now;cnt[now]++;//记录编号,同时记录这种插座有几个        }        scanf("%d",&m);        for(int i=0;i<m;i++){            string x,y;cin>>x>>y;            tot[ID(y)]++;//记录这种插座有几个人用        }        int change;scanf("%d",&change);        for(int i=1;i<=change;i++){            string x,y;cin>>x>>y;            pic[ID(x)][ID(y)]=m;//相互转换        }        build();        dinic();    }    return 0;}
0 0
原创粉丝点击