http://acm.whu.edu.cn/learn/problem/detail?problem_id=1124
题目大意:有N支球队,你们是第N支。每个队伍已经有一些分数了,接下来还有M场比赛。每场比赛有两支参赛队伍,赢得队得2分,输的队不得分,平局各得一分。现在你可以操控所有比赛的胜负。问你最后你们队是否能成为第一名(分数严格大于其他所有队分数)
分析:第一道用满流来解决问题的题。首先明确我们能做两种伎俩。一是我们参与的比赛肯定选我们赢。然后我们不参与的比赛就通过压制分数高的队让他们分数没有我们高,这个trick比较难不是贪心能解决的。首先对于有N参加的比赛,肯定是赢了最好,暂时先不考虑其他的比赛,这是如果各队的积分有大于或等于第N队的,那么肯定是输出NO的。接下来考虑其他的比赛,对于任意队伍i而言,得分是不等等于或者超过score[N]的,因此可以将i和汇点连一条容量为score[N]-score[i]-1的边,由于比赛的总积分是2,自然谁参加哪场比赛就对应连若干容量为2的边即可,这样做最大流,如果最后能够满流就说明所有的比赛都能安排妥当。
建边方案:
1)将源点拆成若干个,分别对应每场比赛,如a和b比一场,则S--2-->S',S'--2-->a,S'--2-->b;
2)不拆点,若a和b比一场,则S--2-->a,a--2(注意不能是inf)-->b;(反例:如a和b赛,b和c赛,则存在a:b:c=0:0:4的结果。)
贴代码(1):
#include<cstdio> #include<cmath> #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<queue> using namespace std; const int maxn=1110,maxm=7000,inf=0x7fffffff; int n,m,a,b,s,t,maxflow,tot=1,flag,p,score[maxn],head[maxn],cur[maxn],h[maxn]; queue<int> q; struct node{ int go,next,v; }e[maxm]; inline int read(){ int x=0;char ch=getchar(); while (ch>'9' || ch<'0')ch=getchar(); while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } inline void addedge(int x,int y,int v){ e[++tot]=(node){y,head[x],v};head[x]=tot; e[++tot]=(node){x,head[y],0};head[y]=tot; } bool bfs(){ for (int i=1;i<=t;i++) h[i]=-1; q.push(s);h[s]=0; while (!q.empty()){ int x=q.front();q.pop(); for (int i=head[x];i;i=e[i].next){ if (e[i].v && h[e[i].go]==-1){ q.push(e[i].go); h[e[i].go]=h[x]+1; } } } return h[t]!=-1; } int dfs(int x,int f){ if (x==t) return f; int tmp,used=0; for (int i=cur[x];i;i=e[i].next){ if (e[i].v && h[e[i].go]==h[x]+1){ tmp=dfs(e[i].go,min(e[i].v,f-used)); e[i].v-=tmp;if (e[i].v) cur[x]=i; e[i^1].v+=tmp;used+=tmp; if (used==f) return f; } } if (!used) h[x]=-1; return used; } void dinic(){ maxflow=0; while (bfs()){ for (int i=1;i<=t;i++) cur[i]=head[i]; maxflow+=dfs(s,inf); } } int main(){ while (scanf("%d%d",&n,&m)!=EOF){ for (int i=1;i<=t;i++) head[i]=0; tot=1;s=n+1;t=1105;p=0;flag=0; for (int i=1;i<=n;i++) score[i]=read(); for (int i=1;i<=m;i++){ a=read();b=read(); if (a==n || b==n) score[n]+=2; else{ p+=2; addedge(s,i+s,2); addedge(i+s,a,2); addedge(i+s,b,2); } } for (int i=1;i<n;i++){ if (score[i]>=score[n]) {flag=1;printf("NO\n");break;} else if (score[n]-1-score[i]) addedge(i,t,score[n]-1-score[i]); } if (flag) continue; dinic(); if (maxflow==p) printf("YES\n"); else printf("NO\n"); } return 0; }
贴代码(2):
#include<cstdio> #include<cmath> #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<queue> using namespace std; const int maxn=1110,maxm=7000,inf=0x7fffffff; int n,m,a,b,s,t,maxflow,tot=1,flag,p,score[maxn],head[maxn],cur[maxn],h[maxn]; queue<int> q; struct node{ int go,next,v; }e[maxm]; inline int read(){ int x=0;char ch=getchar(); while (ch>'9' || ch<'0')ch=getchar(); while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } inline void addedge(int x,int y,int v){ e[++tot]=(node){y,head[x],v};head[x]=tot; e[++tot]=(node){x,head[y],0};head[y]=tot; } bool bfs(){ for (int i=1;i<=t;i++) h[i]=-1; q.push(s);h[s]=0; while (!q.empty()){ int x=q.front();q.pop(); for (int i=head[x];i;i=e[i].next){ if (e[i].v && h[e[i].go]==-1){ q.push(e[i].go); h[e[i].go]=h[x]+1; } } } return h[t]!=-1; } int dfs(int x,int f){ if (x==t) return f; int tmp,used=0; for (int i=cur[x];i;i=e[i].next){ if (e[i].v && h[e[i].go]==h[x]+1){ tmp=dfs(e[i].go,min(e[i].v,f-used)); e[i].v-=tmp;if (e[i].v) cur[x]=i; e[i^1].v+=tmp;used+=tmp; if (used==f) return f; } } if (!used) h[x]=-1; return used; } void dinic(){ maxflow=0; while (bfs()){ for (int i=1;i<=t;i++) cur[i]=head[i]; maxflow+=dfs(s,inf); } } int main(){ while (scanf("%d%d",&n,&m)!=EOF){ for (int i=1;i<=t;i++) head[i]=0; tot=1;s=n+1;t=1105;p=0;flag=0; for (int i=1;i<=n;i++) score[i]=read(); for (int i=1;i<=m;i++){ a=read();b=read(); if (a==n || b==n) score[n]+=2; else{ p+=2; addedge(s,a,2); addedge(a,b,2); } } for (int i=1;i<n;i++){ if (score[i]>=score[n]) {flag=1;printf("NO\n");break;} else if (score[n]-1-score[i]) addedge(i,t,score[n]-1-score[i]); } if (flag) continue; dinic(); if (maxflow==p) printf("YES\n"); else printf("NO\n"); } return 0; }