2597: [Wc2007]剪刀石头布 费用流

来源:互联网 发布:国泰君安网络金融部 编辑:程序博客网 时间:2024/05/17 22:22

应该是费用流boss题了吧…
Oxer神犇的题解
有点方

#include<iostream>#include<cstdio>#include<cstring>#define N 12005#define mod 12005#define M 200005#define inf 1000000007using namespace std;int n,S,T,cnt=1,ans;int head[N],path[N],dis[N],q[N];int next[M],list[M],from[M],cost[M],flow[M];bool vis[N];int a[105][105],edge[105][105];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 calc(int x,int y){    if (x>y) swap(x,y);    return x*n+y;}inline bool spfa(){    for (int i=0;i<=T;i++) dis[i]=inf;    int t=0,w=1,x;    q[1]=S; dis[S]=0; vis[S]=true;    while (t!=w)    {        t=(t+1)%mod;        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]]=true;                    w=(w+1)%mod;                    q[w]=list[i];                }            }        vis[x]=false;    }    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]])        flow[i]-=x,flow[i^1]+=x,ans-=x*cost[i];}int main(){    n=read(); T=n*(n+1)+1;     for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            a[i][j]=read();    ans=n*(n-1)*(n-2)/6;    for (int i=1;i<=n;i++)        for (int j=0;j<n;j++)            insert(S,i,1,j),insert(i,S,0,-j);    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)        {            int id=calc(i,j);            if (a[i][j]!=0)                insert(i,id,1,0),insert(id,i,0,0),edge[i][j]=cnt-1;            if (i<j)                 insert(id,T,1,0),insert(T,id,0,0);        }    while (spfa()) mcf();    printf("%d\n",ans);    for (int i=1;i<=n;i++)    {        for (int j=1;j<=n;j++)        {            if (a[i][j]!=2) printf("%d ",a[i][j]);            else flow[edge[i][j]]?printf("0 "):printf("1 ");        }        puts("");    }    return 0;}
0 0