poj1149 PIGS

传送门

优化建图的起点题...

(好像是邱神讲的第一道网络流?)

然后做的时候完全忘了怎么建图

起手思路是

1.猪圈连源点,顾客连汇点,边权分别是猪数和购买力

2.每个猪圈向第一个顾客连边(inf)

3.持有同一把钥匙顾客之间连边(inf)

然后考虑所有的猪圈向外只有一个inf

所以这一倍的点可以缩掉 直接顾客连源点就行了

Code:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<iostream>
  5 #include<algorithm>
  6 #define ms(a,b) memset(a,b,sizeof a)
  7 #define rep(i,a,n) for(int i = a;i <= n;i++)
  8 #define per(i,n,a) for(int i = n;i >= a;i--)
  9 #define inf 2147483647
 10 using namespace std;
 11 typedef long long ll;
 12 typedef double D;
 13 #define eps 1e-8
 14 ll read() {
 15     ll as = 0,fu = 1;
 16     char c = getchar();
 17     while(c < '0' || c > '9') {
 18         if(c == '-') fu = -1;
 19         c = getchar();
 20     }
 21     while(c >= '0' && c <= '9') {
 22         as = as * 10 + c - '0';
 23         c = getchar();
 24     }
 25     return as * fu;
 26 }
 27 const int N = 1005;
 28 //head
 29 int n,m;
 30 int s = N-2,t = N-1;
 31 int head[N],nxt[100005],mo[100005],cst[100005],cnt = 1;
 32 void _add(int x,int y,int w) {
 33     mo[++cnt] = y;
 34     cst[cnt] = w;
 35     nxt[cnt] = head[x];
 36     head[x] = cnt;
 37 }
 38 void add(int x,int y,int w) {
 39     if(x^y) _add(x,y,w),_add(y,x,0);
 40 }
 41 
 42 int dep[N],cur[N];
 43 bool bfs() {
 44     queue<int> q;
 45     memcpy(cur,head,sizeof cur);
 46     ms(dep,0),q.push(s),dep[s] = 1;
 47     while(!q.empty()) {
 48         int x = q.front();
 49         q.pop();
 50         for(int i = head[x];i;i = nxt[i]) {
 51             int sn = mo[i];
 52             if(!dep[sn] && cst[i]) {
 53                 dep[sn] = dep[x] + 1;
 54                 q.push(sn);
 55             }
 56         }
 57     }
 58     return dep[t];
 59 }
 60 
 61 int dfs(int x,int flow) {
 62     if(x == t || flow == 0) return flow;
 63     int res = 0;
 64     for(int &i = cur[x];i;i = nxt[i]) {
 65         int sn = mo[i];
 66         if(dep[sn] == dep[x] + 1 && cst[i]) {
 67             int d = dfs(sn,min(cst[i],flow - res));
 68             if(d) {
 69                 cst[i] -= d,cst[i^1] += d;
 70                 res += d;
 71                 if(res == flow) break;
 72             }
 73         }
 74     }
 75     if(res ^ flow) dep[x] = 0;
 76     return res;
 77 }
 78 
 79 int DINIC() {
 80     int ans = 0;
 81     while(bfs()) ans += dfs(s,inf);
 82     return ans;
 83 }
 84 
 85 int a[N],fir[N];
 86 int val[N];
 87 //fir表示第一个打开猪圈i的顾客
 88 void init() {
 89     m = read();
 90     n = read();
 91     ms(head,0),ms(fir,0),ms(val,0);
 92     rep(i,1,m) a[i] = read();
 93     rep(i,1,n) {
 94         int X = read();
 95         rep(j,1,X) {
 96             int c = read();
 97             // printf("%d %d %d
",i,c,fir[c]);
 98             fir[c] ? add(fir[c],i,inf) : void(val[i] += a[c]);
 99             fir[c] = i;
100         }
101         add(s,i,val[i]),add(i,t,read());
102     }
103     printf("%d
",DINIC());
104 }
105 int main() {init();}
原文地址:https://www.cnblogs.com/yuyanjiaB/p/10011094.html