sgu 326(经典网络流构图)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13349

题目大意:有N个球队在同一个赛区,已知他们胜利的场数,还剩下的在赛区内的比赛数和跨赛区的比赛数的和,和在赛区内的比赛对阵矩阵。问,1号球队是否可以不小于其余球队胜利场数的最大值。

感觉大牛的思路很好:先贪心一下,让1号球队赢得所有比赛,其余球队输掉所有跨赛区的比赛。如果此时有球队比1号球队胜利场次多,显然直接输出NO。否则,对于在同一赛区的比赛,我们这样构图。新增源点S,汇点T。对于每个点I,从S向I连一条容量为和1号球队胜利场数之差的弧。对于赛区内的每一个进行K次的对阵(I,J),新增一个点P,从I向P连一条容量为K的弧,从J向P连一条容量为K的弧,从P向T连一条容量为K的弧。这样,去一遍最大流,若所有P指向T的弧都满流,则输出YES,否则输出NO。为什么说所有P指向T的弧都满流就是YES的?假设某条P指向T的弧不满流,则S指向I和S指向J的弧已经满流,但是还比赛还没有打完,不管剩下的比赛谁赢都将比1号球队的胜利场次多。所以若所有P指向T的弧都满流,则输出YES,否则输出NO。

  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<queue>

  6 using namespace std;

  7 #define MAXN 1111

  8 #define MAXM 1111111

  9 #define inf 1<<30

 10 

 11 struct Edge{

 12     int v,cap,next;

 13 }edge[MAXM];

 14 

 15 int n,vs,vt,NE,NV;

 16 int head[MAXN];

 17 

 18 void Insert(int u,int v,int cap)

 19 {

 20     edge[NE].v=v;

 21     edge[NE].cap=cap;

 22     edge[NE].next=head[u];

 23     head[u]=NE++;

 24 

 25     edge[NE].v=u;

 26     edge[NE].cap=0;

 27     edge[NE].next=head[v];

 28     head[v]=NE++;

 29 

 30 }

 31 

 32 int level[MAXN],gap[MAXN];

 33 void bfs(int vt)

 34 {

 35     memset(level,-1,sizeof(level));

 36     memset(gap,0,sizeof(gap));

 37     level[vt]=0;

 38     gap[0]++;

 39     queue<int>que;

 40     que.push(vt);

 41     while(!que.empty()){

 42         int u=que.front();

 43         que.pop();

 44         for(int i=head[u];i!=-1;i=edge[i].next){

 45             int v=edge[i].v;

 46             if(level[v]!=-1)continue;

 47             level[v]=level[u]+1;

 48             gap[level[v]]++;

 49             que.push(v);

 50         }

 51     }

 52 }

 53 

 54 int pre[MAXN],cur[MAXN];

 55 int SAP(int vs,int vt)

 56 {

 57     bfs(vt);

 58     memset(pre,-1,sizeof(pre));

 59     memcpy(cur,head,sizeof(head));

 60     int u=pre[vs]=vs,aug=inf,maxflow=0;

 61     gap[0]=NV;

 62     while(level[vs]<NV){

 63         bool flag=false;

 64         for(int &i=cur[u];i!=-1;i=edge[i].next){

 65             int v=edge[i].v;

 66             if(edge[i].cap>0&&level[u]==level[v]+1){

 67                 flag=true;

 68                 aug=min(aug,edge[i].cap);

 69                 pre[v]=u;

 70                 u=v;

 71                 if(v==vt){

 72                     maxflow+=aug;

 73                     for(u=pre[u];v!=vs;v=u,u=pre[u]){

 74                         edge[cur[u]].cap-=aug;

 75                         edge[cur[u]^1].cap+=aug;

 76                     }

 77                     aug=inf;

 78                 }

 79                 break;

 80             }

 81         }

 82         if(flag)continue;

 83         int minlevel=NV;

 84         for(int i=head[u];i!=-1;i=edge[i].next){

 85             int v=edge[i].v;

 86             if(edge[i].cap>0&&level[v]<minlevel){

 87                 minlevel=level[v];

 88                 cur[u]=i;

 89             }

 90         }

 91         if(--gap[level[u]]==0)break;

 92         level[u]=minlevel+1;

 93         gap[level[u]]++;

 94         u=pre[u];

 95     }

 96     return maxflow;

 97 }

 98 

 99 int a[44],b[44];

100 int map[44][44];

101 int main()

102 {

103     int sum=0,flag;

104     while(~scanf("%d",&n)){

105         for(int i=1;i<=n;i++)scanf("%d",&a[i]);

106         for(int i=1;i<=n;i++)scanf("%d",&b[i]);

107         for(int i=1;i<=n;i++)

108             for(int j=1;j<=n;j++)

109                 scanf("%d",&map[i][j]);

110         sum=a[1]+b[1];

111         flag=0;

112         for(int i=2;i<=n;i++){

113             if(sum<a[i]){

114                 flag=1;

115                 break;

116             }

117         }

118         if(flag){

119             puts("NO");

120             continue;

121         }

122         vs=0,vt=n*n+n+1,NV=vt+1;

123         NE=0;

124         memset(head,-1,sizeof(head));

125         for(int i=2;i<=n;i++)Insert(vs,i,sum-a[i]);

126         sum=0;

127         for(int i=2;i<=n;i++){

128             for(int j=i+1;j<=n;j++){

129                 if(map[i][j]>0){

130                     sum+=map[i][j];

131                     Insert(i,i*n+j,map[i][j]);

132                     Insert(j,i*n+j,map[i][j]);

133                     Insert(i*n+j,vt,map[i][j]);

134                 }

135             }

136         }

137         if(SAP(vs,vt)==sum){

138             puts("YES");

139         }else 

140             puts("NO");

141     }

142     return 0;

143 }

144         
View Code

 

你可能感兴趣的:(网络流)