现在的位置: 首页 > 算法 > 正文

poj 1698 Alice’s Chance (最大流Dinic)

2018年09月22日 算法 ⁄ 共 1923字 ⁄ 字号 评论关闭

题目链接:   poj 1689

题目大意:   有个人想拍n部电影,每部电影限定每周哪几天可以拍

                  并且必须在第ki周之前把这部电影拍完,问能否拍完n部电影

解题思路:  把每部电影当作一个顶点,源点指向这些顶点,容量为该电影需要拍多少天

                  然后把每一天都当作顶点,某个工作可以在这天完成就连容量为1大边

                  每天的顶点指向汇点,容量也为1

                  最后求出最大流,满流则说明可以完成这些工作

                  PS:用邻接表时要注意反向边也要加入,因为需要不断增广直到最优解

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 402
#define INF 0x3f3f3f3f
int n,m,S,E,Index,visit[MAX],flag[MAX][MAX],Map[MAX][MAX],listb[MAX];
struct snode{
    int to,c,next;
}Edge[MAX*MAX];
struct node{
    int c;
}edge[MAX][MAX];
int a[60][10],pre[MAX];

int Min(int a,int b)
{
    return (a<b)?a:b;
}

void Add_edge(int a,int b,int c)
{
    Edge[Index].c=c,Edge[Index].to=b;
    Edge[Index].next=pre[a];
    pre[a]=Index++;
}

bool BFS()
{
    int i,s,e,v;
    s=e=0;
    memset(visit,0,sizeof(visit));
    memset(flag,0,sizeof(flag));
    visit[S]=1;
    listb[s++]=S;
    while(s!=e)
    {
        v=listb[e++];
        if(v==E)
            return true;
        for(int i1=pre[v];i1!=-1;i1=Edge[i1].next)
        {
            i=Edge[i1].to;
            if(Map[v][i]&&!visit[i])
            {
                flag[v][i]=1;
                visit[i]=1;
                listb[s++]=i;
            }
        }
    }
    return false;
}

int DFS(int v,int sum)
{
    int s,t,i,to;
    s=sum;
    if(v==E||sum==0)
        return sum;
    for(i=pre[v];i!=-1;i=Edge[i].next)
    {
        to=Edge[i].to;
        if(flag[v][to])
        {
            t=DFS(to,Min(sum,Map[v][to]));
            Map[v][to]-=t;
            Map[to][v]+=t;
            sum-=t;
        }
    }
    return s-sum;
}

void Solve()
{
    while(BFS())
        DFS(S,INF);
}

int main()
{
    int i,j,Max,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        S=Max=Index=0;
        memset(edge,0,sizeof(edge));
        memset(pre,-1,sizeof(pre));
        memset(Map,0,sizeof(Map));
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=9;j++)
            {
                scanf("%d",&a[i][j]);
            }
            if(a[i][9]>Max)
                Max=a[i][9];
            edge[S][i].c=a[i][8];   //前面
            Map[S][i]=a[i][8];      //前面
        }
        E=n+(Max*7)+1;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=a[i][9];j++)
            {
                for(int j1=1;j1<=7;j1++)
                {
                    if(a[i][j1]==1)
                    {
                        edge[i][n+(j-1)*7+j1].c=1;   //中间
                        Map[i][n+(j-1)*7+j1]=1;      //中间
                        edge[n+(j-1)*7+j1][E].c=1;   //后面
                        Map[n+(j-1)*7+j1][E]=1;      //后面
                    }
                }
            }
        }
        for(i=S;i<=E;i++)
        {
            for(j=S;j<=E;j++)
            {
                if(edge[i][j].c)
                {
                    Add_edge(i,j,edge[i][j].c);
                    Add_edge(j,i,-edge[i][j].c);  //不存在,但是需要用到
                }
            }
        }
        Solve();
        int pd=1;
        for(i=1;i<=n;i++)
        {
            if(Map[S][i]!=0)
            {
                pd=0;
                break;
            }
        }
        if(pd)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

抱歉!评论已关闭.