zoj3348 网络流

来源:互联网 发布:数据库开发工程师招聘 编辑:程序博客网 时间:2024/06/11 09:42

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) andm(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 2DD winsty winDD owen lose2winsty owenDD owen3 3DD winsty winDD owen losewinsty owen lose2owen winstyowen DD

Sample Output

YesNo


题意:有n个人,已知前面m场比赛的最终情况和后面将比的p场比赛,问最后DD有没有可能赢

一开始,我以为先对每个人计数,然后后面p场比赛,只要DD都赢,其他比赛只要得分小的+1,后来发现都是相等的时候,每个决策都可能跟后面结果有关,顿时没思路,看了题解才知道是网络流

思路:

前面先把DDhash一下,保存在第0位。然后对前面m场比赛进行哈希跟计算每个人赢了几场

然后是接下来的p场比赛。先让hash值较小的赢,并且记录它赢了对方几场

最后是建图了,首先设源点为s(我用了0表示,是因为DD这个点不需要用到,所以就拿来用),汇点为e(总结点+1)

总共需要三种边:

①edge(s,i,cou[i]):即s到除DD外的每个点都有一条流量为i胜了几场的边

②edge(i,e,cou[0]-1):即除DD外的每个点到汇点都有一条流量为DD最多胜几场-1,保证其他人赢的没DD多

③edge(i,j,E[i][j]):之前我们假设让hash值小的赢,所以我们让他们间有一条边可以流过去

把除DD外,所有人胜的场次加起来为sum,当s到e的最大流等于sum时,则剩下的p场比赛可以把他们每个人胜的情况分散,使得他们都不超过DD胜的次数。否则,比sum小,表示一定存在至少一条,它被“截流”了。

#include <cstdio>#include <cstring>#include <iostream>#include <string>#include <algorithm>#include <map>#include <vector>using namespace std;const int N = 55;const int INF = 0x3f3f3f3f;struct Node{    int to;//终点    int cap; //容量    int rev;  //反向边};vector<Node> v[N];bool used[N];void add_Node(int from,int to,int cap)  //重边情况不影响{    v[from].push_back((Node){to,cap,v[to].size()});    v[to].push_back((Node){from,0,v[from].size()-1});}int dfs(int s,int t,int f){    if(s==t)        return f;    used[s]=true;    for(int i=0;i<v[s].size();i++)    {        Node &tmp = v[s][i];  //注意        if(used[tmp.to]==false && tmp.cap>0)        {            int d=dfs(tmp.to,t,min(f,tmp.cap));            if(d>0)            {                tmp.cap-=d;                v[tmp.to][tmp.rev].cap+=d;                return d;            }        }    }    return 0;}int max_flow(int s,int t){    int flow=0;    for(;;){        memset(used,false,sizeof(used));        int f=dfs(s,t,INF);        if(f==0)            return flow;        flow+=f;    }}int cou[55];int E[55][55];map<string,int> mp;void init(int n){//每个样例需先初始化边集数组 for(int i=0;i<n;i++){v[i].clear();}mp.clear();mp["DD"]=0;memset(cou,0,sizeof(cou));memset(E,0,sizeof(E));}int main(){int n,m,p,idx;int x,y;string a,b;char str[10];while(~scanf("%d%d",&n,&m)){init(n),idx=0;while(m--){cin>>a>>b>>str;if(mp.count(a)==0) mp[a]=++idx;if(mp.count(b)==0) mp[b]=++idx;if(str[0]=='w') cou[mp[a]]++;else cou[mp[b]]++;}scanf("%d",&p);while(p--){cin>>a>>b;if(mp.count(a)) x=mp[a];else x=mp[a]=++idx;if(mp.count(b)) y=mp[b];else y=mp[b]=++idx;if(y<x) x=x^y,y=x^y,x=x^y;cou[x]++;E[x][y]++;}if(cou[0]==0){if(n==1) printf("Yes\n");else printf("No\n");continue;}int s=0;int e=idx+1;int up=cou[0]-1;int sum=0;for(int i=1;i<=idx;i++){sum+=cou[i];add_Node(s,i,cou[i]);add_Node(i,e,up);for(int j=i+1;j<=idx;j++)if(E[i][j])add_Node(i,j,E[i][j]);}int ans=max_flow(s,e);if(ans==sum) printf("Yes\n");else printf("No\n");}    return 0;}



0 0
原创粉丝点击