hdu 4888 Redraw Beautiful Drawings

题目是一个矩阵,每行每列的数字的和都有一个上限,问是否存在可行方案,并且可行方案是否唯一。

第一问比较简单,行列建图,s到每个行节点容量为该行上限,每个列节点连接到t,容量为该列的上限,求最大流,如果满流则有可行方案。第二问就是判断最大流是否唯一,就是在原图中找一个环(经过一条边后不能马上走反向边),环上的边cap-flow都大于0。如果有这个环,那么不唯一,否则唯一。因为流量为k的两个流量图的差别肯定是一个个的环,否则流量不相同,只要按照这个环进行流量的重新分配就可以找到另一个方案。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define maxn 1000
#define INF 10000000
struct Edge
{
    int from, to, cap, flow;
}edges[360000];

int n, m, s, t, kk, cnt;
vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn];        // BFS使用
int d[maxn];           // 从起点到i的距离
int cur[maxn];         // 当前弧指针
int map[410][410];
void AddEdge(int from, int to, int cap)
{
    edges[cnt].from=from;
    edges[cnt].to=to;
    edges[cnt].cap=cap;
    edges[cnt].flow=0;
    G[from].push_back(cnt);
    cnt++;
    edges[cnt].from=to;
    edges[cnt].to=from;
    edges[cnt].cap=0;
    edges[cnt].flow=0;
    G[to].push_back(cnt);
    cnt++;
}
bool BFS()
{
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(s);
    vis[s] = 1;
    d[s] = 0;
    while(!Q.empty())
    {
        int x = Q.front(); Q.pop();
        for(int i = 0; i < G[x].size(); i++)
        {
            Edge& e = edges[G[x][i]];
            if(!vis[e.to] && e.cap > e.flow)
            {
                vis[e.to] = 1;
                d[e.to] = d[x] + 1;
                Q.push(e.to);
            }
        }
    }
    return vis[t];
}
int DFS(int x, int a)
{
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int& i = cur[x]; i < G[x].size(); i++)
    {
        Edge& e = edges[G[x][i]];
        if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0)
        {
            e.flow += f;
            edges[G[x][i]^1].flow -= f;
            flow += f;
            a -= f;
            if(a == 0) break;
        }
    }
    return flow;
}
int Maxflow()
{
    int flow = 0;
    while(BFS())
    {
        memset(cur, 0, sizeof(cur));
        flow += DFS(s, INF);
    }
    return flow;
}

int dfs(int x,int fa)
{
    int i;
    for(i=0;i<G[x].size();i++)
    {
        int v=edges[G[x][i]].to;
        int cap=edges[G[x][i]].cap;
        int flow=edges[G[x][i]].flow;
        if(v==fa) continue;
        if(v!=s&&v!=t&&cap-flow)
        {
            if(vis[v]) return 1;
            vis[v]=1;
            if(dfs(v,x)) return 1;
            vis[v]=0;
        }
    }
    return 0;
}
int main()
{
    while(scanf("%d%d%d",&n,&m,&kk)!=EOF)
    {
        int i,j,x;
        int flag=0;
        int sum1=0,sum2=0;
        s=0;t=n+m+1;cnt=0;
        for(i=0;i<=t;i++) G[i].clear();
        for(i=1;i<=n;i++) {scanf("%d",&x); sum1+=x; AddEdge(s,i,x);}
        for(i=1;i<=m;i++) {scanf("%d",&x); sum2+=x; AddEdge(i+n,t,x);}
        if(sum1!=sum2) {printf("Impossible\n"); continue;}
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                AddEdge(i,j+n,kk);
        if(Maxflow()!=sum1) {printf("Impossible\n"); continue;}
        memset(vis,0,sizeof(vis));
        for(i=1;i<=n;i++)
        {
            vis[i]=1;
            if(dfs(i,-1))
            {
                flag=1;
                break;
            }
            vis[i]=0;
        }
        if(flag==1) printf("Not Unique\n");
        else
        {
            printf("Unique\n");
            for(j=1;j<=n;j++)
                for(i=0;i<G[j].size();i++)
                {
                    int v=edges[G[j][i]].to;
                    if(v!=s)
                        map[j][v-n]=edges[G[j][i]].flow;
                }
            for(i=1;i<=n;i++)
            {
                printf("%d",map[i][1]);
                for(j=2;j<=m;j++)
                    printf(" %d",map[i][j]);
                printf("\n");
            }
        }
    }
    return 0;
}

 

hdu 4888 Redraw Beautiful Drawings

上一篇:eclipse + JBoss 5 + EJB3开发指南(11):实体Bean的连接策略(JOINED Strategy)


下一篇:FindWindow使用方法