Kattis

来源:互联网 发布:杭州 政府网站 建站 编辑:程序博客网 时间:2024/05/21 08:45

题目链接:点击打开链接

刚开始拿到这个题目的时候以为是高斯消元法,对于每个方格四周的边的数量设未知数解方程,后面仔细想了想,缺乏可行性,时间复杂度和空间复杂度太高了。后面终于想到网络流上面去了,可是对于每个点都要控制流量,而且每条边的流量又被多个点控制,然后越想越迷糊。

想了两天了终于意识到这个是个二分图,然后二分图根据每个点的颜色,选择与源点或者汇点建边,点与点之间根据能否增流建边。(写的很粗糙,不负责地说下次什么时候想起来的时候再改改吧~~~~~)

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <vector>using namespace std;const int inf=0x3f3f3f3f;const int N=200;int L[]={0,1,0,-1};int R[]={1,0,-1,0};char Graph[N<<1][N<<1];struct edge_t{    int v,c,next;}edge[N*N*4];int Ecnt;int vertex[N*N];void init_Graph(){    Ecnt=0;    memset(vertex,-1,sizeof(vertex));}void make_edge(int u,int v,int c){    edge[Ecnt].v=v;    edge[Ecnt].c=c;    edge[Ecnt].next=vertex[u];    vertex[u]=Ecnt++;    edge[Ecnt].v=u;    edge[Ecnt].c=0;    edge[Ecnt].next=vertex[v];    vertex[v]=Ecnt++;}int LL[N*N];bool bfs(int s,int t){    memset(LL,-1,sizeof(LL));    vector<int> q;    q.push_back(s);    LL[s]=0;    while(!q.empty())    {        int u=q.back();        q.pop_back();        for(int i=vertex[u]; i!=-1; i=edge[i].next)        {            if(edge[i].c<=0) continue;            int v=edge[i].v;            if(-1!=LL[v]) continue;            q.push_back(v);            LL[v]=LL[u]+1;        }    }    return -1!=LL[t];}int dfs(int u,int cf,int t){    if(u==t) return cf;    int tf=0;    for(int i=vertex[u]; i!=-1; i=edge[i].next)    {        int v=edge[i].v;        int c=edge[i].c;        if(LL[u]+1==LL[v]&&c>0&&cf>tf)        {            int f=dfs(v,min(c,cf-tf),t);            if(0==f) continue;            edge[i].c-=f;            edge[i^1].c+=f;            tf+=f;        }    }    if(0==tf) LL[u]=-1;    return tf;}int Dinic(int s,int t){    int ret=0;    while(bfs(s,t))    {        int ans;        while(ans=dfs(s,inf,t))            ret+=ans;    }    return ret;}inline int Gethash(int x,int y,int N){    return x*N+y;}int main(){    int N;    while(scanf("%d",&N)!=EOF)    {        init_Graph();        int s=(N+1)*(N+1),e=(N+1)*(N+1)+1;        //唯一难点,边缘上的点怎么建图        for(int i=0;i<2*N-1;i++)            scanf("%s",Graph[i]);        for(int i=0;i<=N;i++)            for(int j=0;j<=N;j++)            {                //因为是二分图,所以染色                int color=(i+j)%2;                int flow=(i==0||j==0||i==N||j==N)?4:3;                int x=2*i-1,y=2*j-1;                for(int k=0;k<4;k++)                {                    int m=x+L[k],n=y+R[k];                    if(m>=0&&m<2*N-1&&n>=0&&n<2*N-1&&Graph[m][n]=='.')                    {                        make_edge(Gethash(i,j,N+1),Gethash(i+L[k],j+R[k],N+1),1);                    }                    else flow--;                }                if(color==0) make_edge(s,Gethash(i,j,N+1),flow);                else make_edge(Gethash(i,j,N+1),e,flow);            }        printf("%d\n",Dinic(s,e)+1);    }    return 0;}

原创粉丝点击