3171: [Tjoi2013]循环格 费用流

来源:互联网 发布:android 解析json 编辑:程序博客网 时间:2024/05/16 16:10

人太弱真是不能活qwq网上都说是裸题结果我还是没想出怎么做。。。
果然思考方向偏了真没治。。

还是要抓住本质考虑:结果是每个点都在一个环里,这是大家都能想到的。更具体地说呢?每个点的入度和出度均为1,这种一分为二的思想,正好适合建立二分图啊!我太sb居然直接没往这个方向想。
想到就比较好做了,还是拆点,左边为入度右边为出度,S->左边每个点,流量1费用0,右边每个点->T,流量1费用0,中间相邻点连边,如果和原来方向一样则费用为0否则为1,流量也是1。

抓住本质考虑问题,建立合适的模型!

#include<iostream>#include<cstdio>#include<cstring>#define M 505#define inf 1000000007using namespace std;int n,m,T,ans,cnt=1;int a[16][16];int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};int head[505],dis[505],q[505],path[505];int next[3005],list[3005],flow[3005],cost[3005],from[3005];bool vis[505];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void insert(int x,int y,int z,int w){    next[++cnt]=head[x];    head[x]=cnt;    from[cnt]=x;    list[cnt]=y;    flow[cnt]=z;    cost[cnt]=w;}inline int c(int i,int j){    return (i-1)*m+j;}inline bool spfa(){    for (int i=0;i<=T;i++) dis[i]=inf;    dis[0]=0; vis[0]=1; q[1]=0;    int t=0,w=1,x;    while (t!=w)    {        t=(t+1)%M;        x=q[t];        for (int i=head[x];i;i=next[i])            if (flow[i]&&dis[list[i]]>dis[x]+cost[i])            {                dis[list[i]]=dis[x]+cost[i];                path[list[i]]=i;                if (!vis[list[i]])                {                    vis[list[i]]=1;                    w=(w+1)%M;                    q[w]=list[i];                }            }        vis[x]=0;    }    return dis[T]!=inf;}inline void mcf(){    int x=inf;    for (int i=path[T];i;i=path[from[i]]) x=min(x,flow[i]);    for (int i=path[T];i;i=path[from[i]])        ans+=x*cost[i],flow[i]-=x,flow[i^1]+=x;}int main(){    n=read(); m=read(); T=2*n*m+1;    for (int i=1;i<=n;i++)    {        char s[25];        scanf("%s",s+1);        for (int j=1;j<=m;j++)            switch (s[j])            {                case 'L':a[i][j]=0; break;                case 'R':a[i][j]=1; break;                case 'U':a[i][j]=2; break;                case 'D':a[i][j]=3; break;            }    }    for (int i=1;i<=n;i++)        for (int j=1;j<=m;j++)            for (int k=0;k<4;k++)            {                int x=i+dx[k],y=j+dy[k];                if (x<1) x=n; if (x>n) x=1;                if (y<1) y=m; if (y>m) y=1;                if (a[i][j]==k)                    insert(c(i,j),c(x,y)+n*m,1,0),insert(c(x,y)+n*m,c(i,j),0,0);                else insert(c(i,j),c(x,y)+n*m,1,1),insert(c(x,y)+n*m,c(i,j),0,-1);            }    for (int i=1;i<=n*m;i++)        insert(0,i,1,0),insert(i,0,0,0),insert(i+n*m,T,1,0),insert(T,i+n*m,0,0);    while (spfa()) mcf();    cout << ans << endl;    return 0;}
0 0
原创粉丝点击