【最大流】【HDU3338】【Kakuro Extension】

来源:互联网 发布:命中注定我爱你 知乎 编辑:程序博客网 时间:2024/05/22 06:42

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3338

题目大意:填数字,使白色区域的值得和等于有值得黑色区域的相对应的值,用网络流来做

题目思路:增加一个源点和汇点,然后左进上出,用源点连左面,容量为相对应的值,汇点连上面,容量是相对应的值,然后左面连空白区域的,容量为8,因为数字为1-9,有下限,但因每个空白必须有值,所以至少为一,所以容量空间为0-8;然后空白区域来连上面,容量同样为8;


#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define INF 999999999#define maxn 14000#define RE(x) (x)^1int head[maxn];int st,ed;//开始节点,结束节点struct Edge{    int v,next;    int val;    Edge() {}    Edge( int V , int NEXT , int W = 0 ):v(V),next(NEXT),val(W) {}} edge[500000];int lvl[maxn], gap[maxn];int cnt_edge;int map[maxn][maxn];struct gg{    int x,y;    int val;} row[maxn],col[maxn];int emp,row_num,col_num;int n,m,T;void Insert_Edge( int u , int v , int flow = 0 ){    edge[cnt_edge] = Edge(v,head[u],flow);    head[u] = cnt_edge++;    edge[cnt_edge] = Edge(u,head[v]);    head[v] = cnt_edge++;}void Init(){    cnt_edge = 0;    memset(head,-1,sizeof(head));    memset(lvl, 0, sizeof (lvl));    memset(gap, 0, sizeof (gap));}int dfs(int u, int flow){    if (u==ed)    {        return flow;    }    int tf = 0, sf, mlvl = ed-1;    for (int i= head[u]; i != -1; i = edge[i].next)    {        if (edge[i].val > 0)        {            if (lvl[u] ==lvl[edge[i].v]+1)            {                sf = dfs(edge[i].v, min(flow-tf, edge[i].val));                edge[i].val -= sf;                edge[RE(i)].val += sf;                tf += sf;                if (lvl[st] >=ed)                {                    return tf;                }                if (tf == flow)                {                    break;                }            }            mlvl = min(mlvl, lvl[edge[i].v]);        }    }    if (tf == 0)    {        --gap[lvl[u]];        if (!gap[lvl[u]])        {            lvl[st] =ed;        }        else        {            lvl[u] = mlvl+1;            ++gap[lvl[u]];        }    }    return tf;}int sap(){    int ans = 0;    gap[0]=ed;    while (lvl[st] <ed)    {        ans += dfs(st, INF);    }    return ans;}int print( int tp ){    int ans = 0;    int id = tp + row_num+1;    for( int i = head[id] ; i != -1 ; i = edge[i].next )    {        int v = edge[i].v;        if( v <=row_num+1 )        {            ans+= edge[i].val;            break;        }    }    return ans+1;}int main(){    int i,j;    char s[15];    //freopen("F://ACMInput/input.txt","r",stdin);    while(scanf("%d%d",&n,&m)!=-1)    {        emp=row_num=col_num=0;        for(i=0; i<n; i++)            for(j=0; j<m; j++)            {                scanf("%s",s);                if(s[0]=='.')                {                    map[i][j]=++emp;                }                else                {                    map[i][j]=-1;                    if(s[4]!='X')                    {                        int tp=(s[4]-'0')*100+(s[5]-'0')*10+s[6]-'0';                        row[++row_num].x=i;                        row[row_num].y=j;                        row[row_num].val=tp;                    }                    if(s[0]!= 'X' )                    {                        int tp = (s[0]-'0')*100+(s[1]-'0')*10+s[2]-'0';                        col[++col_num].x = i;                        col[col_num].y = j;                        col[col_num].val = tp;                    }                }            }        T=emp+col_num+row_num+2;        st=1;        ed=T;        Init();        for(i=1; i<=row_num; i++)        {            int pos = i;            int x = row[i].x;            int y = row[i].y;            int cnt_len = 0;            for( y=y+1; y <m ; y++ )            {                if( map[x][y] != -1 )                {                    cnt_len++;                    Insert_Edge(i+1, row_num+ map[x][y]+1,8);                }                else break;            }            Insert_Edge(st,pos+1,row[i].val-cnt_len);        }        for( i = 1 ; i <=col_num ; i++ )        {            int pos =i+1+row_num+emp;            int x = col[i].x;            int y = col[i].y;            int cnt_len = 0;            for( x=x+1 ; x < n ; x++ )            {                if( map[x][y] != -1 )                {                    cnt_len++;                    Insert_Edge(row_num+ map[x][y]+1,pos,8);                }                else break;            }            Insert_Edge(pos,ed,col[i].val-cnt_len);        }        sap();        for(i=0; i<n; i++)        {            for(j=0; j<m; j++)            {                if(map[i][j]==-1)                    printf("_ ");                else                    printf("%d ",print(map[i][j]));            }            printf("\n");        }    }    return 0;}


0 0