poj 1698 最大流sap
/* 题意:女孩拍片,每部电影只能在每周固定的几天里面拍,总共需要拍D天,并且需要在W周内拍完,女孩 每天只能为一部电影拍片,问女孩是否能全部拍完。 题解:最大流; 建图:将每个星期化为总的每一天为W*7个点,每部电影为N个点,电影在哪天可以拍则加入一条有向边, 并且权值为1,这样保证当天同一部只能拍一天;加入源点连接各个电影的结点,权值为需求D,最后加入 汇点,每一天都连接向这个汇点,权值分别为1,最终求出最大流若与电影天数总和相等则可以拍完。 */ #include <cstdio> #include <cstring> #define EMAX 15000 #define VMAX 400 const int INF = 0xfffffff; int head[VMAX],dis[VMAX],cur[VMAX],gap[VMAX],pre[VMAX]; int map[VMAX][VMAX]; int EN; struct edge { int from,to; int weight; int next; }e[EMAX]; void insert(int u,int v,int w) { e[EN].from = u; e[EN].to = v; e[EN].weight = w; e[EN].next = head[u]; head[u] = EN++; e[EN].weight = 0; e[EN].from = v; e[EN].to = u; e[EN].next = head[v]; head[v] = EN++; } int sap(int s,int t, int n)//sap模版求最大流 { memset(dis,0,sizeof(dis)); memset(gap,0,sizeof(gap)); for(int i=0; i<=n; i++) cur[i] = head[i]; int u = pre[s]; pre[s] = s; int ret = 0; int temp = -1; gap[0] = n; bool flag; while(dis[s] < n) { flag = false; for(int &i = cur[u]; i != -1; i = e[i].next) { int v = e[i].to; if(e[i].weight && dis[u] == dis[v] + 1) { if (temp == -1 || temp>e[i].weight) temp = e[i].weight; pre[v] = u; u = v; if(v == t) { ret += temp; for(u = pre[u];v != s;v = u,u = pre[u]) { e[cur[u]].weight -= temp; e[cur[u]^1].weight += temp; } temp = -1; } flag = true; break; } } if (flag) continue; int mindis = n; for(int i = head[u]; i != -1 ; i = e[i].next) { int v = e[i].to; if(e[i].weight && mindis > dis[v]) { cur[u] = i; mindis = dis[v]; } } gap[dis[u]]--; if( gap[dis[u]] == 0) break; dis[u] = mindis+1; gap[dis[u]]++; u = pre[u]; } return ret; } int main(void) { int t,n,sum,d,w; int week[8]; scanf("%d",&t); while (t--) { memset(head,-1,sizeof(head)); sum = EN = 0; scanf("%d",&n); int max = -1; for(int i=1; i<=n; i++) { for(int j=1; j<=7; j++) scanf("%d",&week[j]); scanf("%d%d",&d,&w); if (max < w) max = w; sum += d; insert(0,i,d);//源点与电影加边 for(int j=1; j<=7; j++)//电影与日期加边 { if (week[j]) { for(int k=0; k<w; k++) insert(i,n+k*7+j,1); } } } for(int i=n+1; i<=n+7*max; i++)//日期与汇点加边 insert(i,n+7*max+1,1); if (sum == sap(0,n+7*max+1,n+7*max+2)) printf("Yes\n"); else printf("No\n"); } return 0; }