【 zoj 3348 】Schedule 【网络流经典建图】

来源:互联网 发布:软件开发外包管理制度 编辑:程序博客网 时间:2024/05/20 16:36

DD enters the top-level pingpong match! As the game going on, he wonders if there is possibility for him to get the champion(excluding joint champions). Now provide you the results of previous matches, and the details of rest matches. You have to judge it.

Input
There are several test cases. You should process to the end of input.

For each test case. the first line contain two integers n (1 <= n <= 50) and m(0 <= m <= 1000), n indicates the number of players. m indicates the matches have ended.

Then for the following m lines, each line has the format: “Player1 Player2 Result”. Player1 and Player2 are the names of the two players, and Result could only be “win” or “lose”.

In the next line there is another integer p (0 <= p <= 5000), indicates the matches that will start later.

Then for the following p lines, each line has the format: “Player1 Player2”, which means Player1 and Player2 will start a match.

We ensure there is a player named “DD”. The length of each player name is no longer than 10.

Output
You should only output “Yes” or “No” for each case, which means if DD has the possibility to be the champion.

Sample Input
3 2
DD winsty win
DD owen lose
2
winsty owen
DD owen
3 3
DD winsty win
DD owen lose
winsty owen lose
2
owen winsty
owen DD

Sample Output
Yes
No

分析 :假设剩下的q场比赛中DD参加了a场,在之前的M场比赛中胜利了b场,我们可以认为这a场都是DD胜利(当然要用临界情况判断,想一下,若下面全赢DD还不是冠军 就肯定没有希望了),这样DD胜利了a+b场。这样问题转化为能否将剩下的q-a场比赛(也就是剩下的P场比赛中DD没有参与的比赛)的胜利分配给除了DD以外的所有n-1人,使得除DD外任意一人的胜场数都小于DD的胜场数。
建图:设源点S,汇点T,把每场比赛虚拟成一个节点。
一:从S向 所有q-a场比赛 引一条容量为1的边;
二:因为每场比赛只有一个胜者,所以每场比赛要向参加比赛的两个选手连边,容量为1,代表这个比赛的胜利只能由两人中的一人获得。
三:除DD外每个人向T连边,容量为a + b - 1-win[i] ,代表每个人的胜利次数不能超过DD胜利的次数。
然后对这个图求最大流,如果最大流小于q-a则代表无法将q-a场比赛的胜利分配给n-1人,则输出NO。

代码

#include<bits/stdc++.h>#define LL long longusing namespace std;const int MAXN = 1e4;const int MAXM = 1e6;const int inf=0x3f3f3f3f;struct Edge {    int from,to,cap,flow,nexts;}edge[MAXM];int head[MAXN],top;int n,m,q;map<string,int>mp;int score[MAXN];int S,T;void init(){    memset(head,-1,sizeof(head));    top=0;}void addedge(int a,int b,int c){    Edge e={a,b,c,0,head[a]};    edge[top]=e;head[a]=top++;    Edge ee={b,a,0,0,head[b]};    edge[top]=ee;head[b]=top++;}int num; // DD在将要开始的比赛中参加的场数int flage; //是否赢void getmap(){    S=0;    mp.clear();    memset(score,0,sizeof(score));    mp["DD"]=1;string a,b,c;    int ge=2;     while(m--){        cin>>a>>b>>c;        if(!mp[a]) mp[a]=ge++;        if(!mp[b]) mp[b]=ge++;            if(c=="win") score[mp[a]]++;             else if(c=="lose") score[mp[b]]++;    }    scanf("%d",&q);    S=0;T=q+n+1;    int DDscore=score[1]; num=0;    for(int i=1;i<=q;i++){        cin>>a>>b;        if(!mp[a]) mp[a]=ge++;        if(!mp[b]) mp[b]=ge++;        if(a=="DD"||b=="DD") { DDscore++; continue;}        num++;        addedge(S,i+n,1);        addedge(i+n,mp[a],1);        addedge(i+n,mp[b],1);    }    flag=1;// 这中情况要特判一下,因为用最大流无法解决这种情况    for(int i=2;i<ge;i++)         if( DDscore<=score[i]) {            flag=0;return ;        }        for(int i=2;i<ge;i++)            addedge(i,T,DDscore-1-score[i]);//DD总赢的场数-1-每个人已经赢的场数}int vis[MAXN],dis[MAXN];int cur[MAXN];bool bfs(int st,int ed){    memset(vis,0,sizeof(vis));    queue<int>Q; Q.push(st);    vis[st]=1;dis[st]=1;    while(!Q.empty()){        int now=Q.front();Q.pop();        for(int i=head[now];i!=-1;i=edge[i].nexts){            Edge e=edge[i];            if(!vis[e.to]&&e.cap-e.flow>0){                vis[e.to]=1;                dis[e.to]=dis[now]+1;                if(e.to==ed)  return 1;                Q.push(e.to);            }        }    }    return 0;}int dfs(int now,int a,int ed){    if(now==ed||a==0) return a;    int flow=0,f;    for(int& i=cur[now];i!=-1;i=edge[i].nexts){        Edge &e=edge[i];        if(dis[e.to]==dis[now]+1&&(f=dfs(e.to,min(a,e.cap-e.flow),ed))>0){            e.flow+=f;            flow+=f;            edge[i^1].flow-=f;            a-=f;            if(a==0) break;        }    }    return flow;}int max_flow(int st,int ed){    int flow=0;    while(bfs(st,ed)){        memcpy(cur,head,sizeof(head));        flow+=dfs(st,inf,ed);    }    return flow;}int main(){    while(~scanf("%d%d",&n,&m)){        init();        getmap();        if(!flag){ puts("No"); continue;}        if(max_flow(S,T)>=num) puts("Yes");        else puts("No");    }    return 0;}
原创粉丝点击