【PowerOJ1742&网络流24题】试题库问题(最大流)

题意:

 思路:

【问题分析】

二分图多重匹配问题,用最大流解决。

【建模方法】

建立二分图,每个类别为X集合中的顶点,每个题为Y集合中的顶点,增设附加源S和汇T。

1、从S向每个Xi连接一条容量为该类别所需数量的有向边。

2、从每个Yi向T连接一条容量为1的有向边。

3、如果一个题i属于一个类别j,连接一条从Xj到Yi容量为1的有向边。

求网络最大流,如果最大流量等于所有类别所需之和,则存在解,否则无解。对于每个类别,从X集合对应点出发的所有满流边,指向的B集合中的顶点就是该类别的所选的题(一个可行解)。

【建模分析】

二分图多重匹配问题。X,Y集合之间的边容量全部是1,保证两个点只能匹配一次,源汇的连边限制了每个点匹配的个数。求出网络最大流,如果流量等于X集合所有点与S边容量之和,那么则说明X集合

每个点都有完备的多重匹配。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef long double ld;
  7 typedef pair<int,int> PII;
  8 typedef pair<ll,ll> Pll;
  9 typedef vector<int> VI;
 10 typedef vector<PII> VII;
 11 typedef pair<ll,ll>P;
 12 #define N  100010
 13 #define M  1000000
 14 #define INF 1e9
 15 #define fi first
 16 #define se second
 17 #define MP make_pair
 18 #define pb push_back
 19 #define pi acos(-1)
 20 #define mem(a,b) memset(a,b,sizeof(a))
 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 23 #define lowbit(x) x&(-x)
 24 #define Rand (rand()*(1<<16)+rand())
 25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 26 #define ls p<<1
 27 #define rs p<<1|1
 28 
 29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 30       double eps=1e-6;
 31       int dx[4]={-1,1,0,0};
 32       int dy[4]={0,0,-1,1};
 33 
 34 VI c[N];
 35 int head[N],vet[N],len[N],nxt[N],a[N],dis[N],s,S,T,tot;
 36 
 37 int read()
 38 {
 39    int v=0,f=1;
 40    char c=getchar();
 41    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 42    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 43    return v*f;
 44 }
 45 
 46 void add(int a,int b,int c)
 47 {
 48     nxt[++tot]=head[a];
 49     vet[tot]=b;
 50     len[tot]=c;
 51     head[a]=tot;
 52 
 53     nxt[++tot]=head[b];
 54     vet[tot]=a;
 55     len[tot]=0;
 56     head[b]=tot;
 57 }
 58 
 59 bool bfs()
 60 {
 61     queue<int>q;
 62     rep(i,1,s) dis[i]=-1;
 63     q.push(S),dis[S]=0;
 64     while(!q.empty())
 65     {
 66         int u=q.front();
 67         q.pop();
 68         int e=head[u];
 69         while(e)
 70         {
 71             int v=vet[e];
 72             if(len[e]&&dis[v]==-1)
 73             {
 74                 dis[v]=dis[u]+1;
 75                 q.push(v);
 76             }
 77             e=nxt[e];
 78         }
 79     }
 80     return dis[T]!=-1;
 81 }
 82 
 83 int dfs(int u,int aug)
 84 {
 85     if(u==T) return aug;
 86     int e=head[u],val=0,flow=0;
 87     while(e)
 88     {
 89         int v=vet[e];
 90         if(len[e]&&dis[v]==dis[u]+1)
 91         {
 92             int t=dfs(v,min(len[e],aug));
 93             if(!t)
 94             {
 95                 e=nxt[e];
 96                 continue;
 97             }
 98             flow+=t;
 99             aug-=t;
100             len[e]-=t;
101             len[e^1]+=t;
102             if(!aug) break;
103         }
104         e=nxt[e];
105     }
106     if(!flow) dis[u]=-1;
107     return flow;
108 }
109 
110 int maxflow()
111 {
112     int res=0;
113     while(bfs()) res+=dfs(S,INF);
114     return res;
115 }
116 
117 int main()
118 {
119     //freopen("1.in","r",stdin);
120     //freopen("1.out","w",stdout);
121     int K=read(),n=read();
122     s=K+n;
123     S=++s,T=++s;
124     rep(i,1,K)
125     {
126         a[i]=read();
127         add(i+n,T,a[i]);
128     }
129     rep(i,1,n)
130     {
131         int x=read();
132         add(S,i,1);
133         rep(j,1,x)
134         {
135             int y=read();
136             add(i,y+n,1);
137         }
138     }
139     int sum=0;
140     rep(i,1,n) sum+=a[i];
141     int flow=maxflow();
142     //printf("sum=%d flow=%d
",sum,flow);
143     if(sum!=flow) printf("No Solution!
");
144      else
145      {
146         rep(i,1,n)
147         {
148             int e=head[i];
149             while(e)
150             {
151                 int v=vet[e];
152                 if(len[e]&&c[v-n].size()<a[v-n])
153                 {
154                     c[v-n].pb(i);
155                     break;
156                 }
157                 e=nxt[e];
158             }
159         }
160         rep(i,1,K)
161         {
162             printf("%d: ",i);
163             for(int j=0;j<c[i].size();j++) printf("%d ",c[i][j]);
164             printf("
");
165         }
166      }
167     return 0;
168 }
原文地址:https://www.cnblogs.com/myx12345/p/11758950.html