poj1698 [ Usaco2007 Feb ] --最大流(Dinic)

题目大意:

      爱丽丝要拍电影,有n部电影,规定爱丽丝每天只能拍一部电影,每部电影在每个礼拜只有固定的几天可以拍电影,只可以拍前面w个礼拜,并且这部电影要拍d天,问爱丽丝能不能拍完所有的电影。

思路:

      建图。点1~350代表天数(因为最多只有350天),点351~370代表电影(最多只有20部电影)。从源点向每部电影连一条容量为d的边,从每部电影向可以拍摄它的那几天连一条容量为1的边,从每天向汇点连一条容量为1的边(限制每天只能拍一部电影)。再求一遍最大流,看其是否与sum(d[i])相等,如果是,就输出Yes,否则输出No。

具体看代码。

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
#define INF 2147483647
vector<int>g[400];
queue<int>q;
struct Edge{
    int to,from,cap,flow;
}edge[160000];
int i,j,k,s,t,n,m,x,y,sum,w,d,cur[400],T,dist[400];
bool a[8],vis[400];
void addedge(int x,int y,int cap){
    edge[m++]=(Edge){y,x,cap,0};
    edge[m++]=(Edge){x,y,0,0};
    g[x].push_back(m-2);
    g[y].push_back(m-1);
}
bool bfs(){
    memset(vis,0,sizeof(vis));
    vis[s]=1;
    dist[s]=0;
    q.push(s);
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=0;i<g[x].size();i++){
            Edge& e=edge[g[x][i]];
            if(e.cap>e.flow&&!vis[e.to]){
                vis[e.to]=1;
                dist[e.to]=dist[x]+1;
                q.push(e.to);
            }
        }
    }
    return vis[t];
}
int dfs(int x,int a){
    if(x==t||!a)return a;
    int flow=0,f;
    for(int& i=cur[x];i<g[x].size();i++){
        Edge& e=edge[g[x][i]];
        if(dist[x]+1==dist[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))){
            e.flow+=f;
            edge[g[x][i]^1].flow-=f;
            flow+=f;
            a-=f;
            if(!a)break;
        }
    }
    return flow;
}
int maxflow(){
    int flow=0;
    while(bfs()){
        memset(cur,0,sizeof(cur));
        flow+=dfs(s,INF);
    }
    return flow;
}
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        sum=m=0;t=351+n;
        for(i=1;i<=n;i++){
            for(j=1;j<=7;j++)scanf("%d",&a[j]);
            scanf("%d%d",&d,&w);
            sum+=d;
            addedge(s,i+350,d);
            for(j=1;j<=7;j++)
            if(a[j])for(k=0;k<w;k++)addedge(i+350,k*7+j,1);
        }
        for(i=1;i<=350;i++)addedge(i,t,1);
        if(maxflow()==sum)printf("Yes
");else printf("No
");
        for(i=0;i<=t;i++)g[i].clear();
    }
    return 0;
}
poj1698
原文地址:https://www.cnblogs.com/gjghfd/p/5794964.html