ZOJ 3348 网络流最大流 解题报告

来源:互联网 发布:手机淘宝微博绑定 编辑:程序博客网 时间:2024/06/11 12:43

Schedule

Time Limit: 1 Second Memory Limit: 32768 KB
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

[解题报告]
题意:有N个参赛队员,其中DD想拿比赛冠军。冠军是赢的场次最多的那个人(不能有和他平齐的)。现在知道M场已经结束的比赛,如 A B win 说明A赢了B 或者A B lose说明A输给B。又给了P场将要进行的比赛以及比赛双方,问DD有没有希望拿冠军。
因为问的是有没有希望拿到冠军,所以我们采用一个贪心的处理:在接下来的p场比赛中假设剩下的P场比赛中,DD参加了a场,则认为这a场都是DD胜利(当然要用临界情况判断,想一下,若下面全赢DD还不是冠军 就肯定没有希望了),这样DD胜利了a+b场(b是之前胜的场数)。这样问题转化为能否将剩下的P-a场比赛(也就是剩下的P场比赛中DD没有参与的比赛)的胜利分配给除了DD以外的所有n-1人,使得除DD外任意一人的胜场数都小于DD的胜场数。
建图:设源点ss,汇点tt,把每场比赛虚拟成一个节点。
从ss向 所有P-a场比赛 引一条容量为1的边;
因为每场比赛只有一个胜者,所以每场比赛要向参加比赛的两个选手连边,容量为1,代表这个比赛的胜利只能由两人中的一人获得。
除DD外每个人向sink连边,容量为a + b - 1,代表每个人的胜利次数不能超过DD胜利的次数。
然后对这个图求最大流,如果最大流小于P-a则代表无法将P-a场比赛的胜利分配给n-1人,则输出NO。
(已开始把map的clear写到后面去了,调了好久…)

代码如下:

#include<cstdio>  #include<cstring> #include<string>#include<algorithm>#include<map>#include<queue>  using namespace std;  #define inf 0x3f3f3f3f  #define maxv 60010#define maxe 200010  int nume=0,head[maxv],e[maxe][3];void inline adde(int i,int j,int c)  {      e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;      e[nume++][2]=c;     e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;      e[nume++][2]=0;  }  int ss,tt,n,m,p;  int vis[maxv],lev[maxv]; bool bfs()  {      for(int i=0;i<maxv;i++)      vis[i]=lev[i]=0;      queue<int>q;      q.push(ss);      vis[ss]=1;      while(!q.empty())      {          int cur=q.front();          q.pop();          for(int i=head[cur];i!=-1;i=e[i][1])          {              int v=e[i][0];              if(!vis[v]&&e[i][2]>0)              {                  lev[v]=lev[cur]+1;                  vis[v]=1;                  q.push(v);              }          }      }      return vis[tt];  }  int dfs(int u,int minf)  {      if(u==tt||minf==0)return minf;      int sumf=0,f;      for(int i=head[u];i!=-1&&minf;i=e[i][1])      {          int v=e[i][0];          if(lev[v]==lev[u]+1&&e[i][2]>0)          {              f=dfs(v,minf<e[i][2]?minf:e[i][2]);              e[i][2]-=f;e[i^1][2]+=f;              sumf+=f;minf-=f;          }      }      if(!sumf) lev[u]=-1;      return sumf;  }  int Dinic()  {      int sum=0;      while(bfs())sum+=dfs(ss,inf);      return sum;  }  map<string,int>fp;int k;int win[maxv];int main() {      while(scanf("%d%d",&n,&m)!=EOF)    {        fp.clear();          nume=0,k=1;        fp["DD"]=1;        memset(head,-1,sizeof(head));        memset(win,0,sizeof(win));        for(int i=1;i<=m;++i)        {            char a[10],b[10],op[10];            scanf("%s%s%s",a,b,op);            if(!fp[a]) fp[a]=++k;            if(!fp[b]) fp[b]=++k;            if(op[0]=='w') ++win[fp[a]];            else ++win[fp[b]];        }        scanf("%d",&p);        ss=0,tt=n+p+1;        int DD_win=win[1],DD_num=0;        for(int i=1;i<=p;++i)        {            char a[10],b[10];            scanf("%s%s",a,b);            if(!fp[a]) fp[a]=++k;            if(!fp[b]) fp[b]=++k;            if(strcmp(a,"DD")==0||strcmp(b,"DD")==0)              {DD_win++;continue;}            ++DD_num;            adde(ss,i+n,1);            adde(i+n,fp[a],1);            adde(i+n,fp[b],1);        }        for(int i=2;i<=k;++i)          {              if(DD_win<=win[i])              {                  printf("No\n");                goto h;            }          }          for(int i=2;i<=k;++i)        adde(i,tt,DD_win-win[i]-1);        (Dinic()<DD_num)?printf("No\n"):printf("Yes\n");        h:;    }    return 0;} 

让我看到你们的双手

原创粉丝点击