zoukankan      html  css  js  c++  java
  • BZOJ2597 WC2007剪刀石头布(费用流)

      考虑使非剪刀石头布情况尽量少。设第i个人赢了xi场,那么以i作为赢家的非剪刀石头布情况就为xi(xi-1)/2种。那么使Σxi(xi-1)/2尽量小即可。

      考虑网络流。将比赛建成一排点,人建成一排点,每场未确定比赛向比赛双方连边,确定比赛向赢者连边,这样就是一种合法的比赛方案了。

      在此基础上控制代价最小。由于每多赢一场非剪刀石头布情况的增量就更大,将边拆开费用设为增量即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 110
    #define S 0
    #define T 10101
    int n,p[N*N],l[N*N],r[N*N],cnt,t=-1,ans,a[N][N];
    int d[N*N],q[N*N],pre[N*N];
    bool flag[N*N];
    struct data{int to,nxt,cap,flow,cost;
    }edge[N*N<<4];
    void addedge(int x,int y,int z,int cost)
    {
        t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=0,edge[t].cost=cost,p[x]=t;
        t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=0,edge[t].cost=-cost,p[y]=t;
    }
    int inc(int &x){x++;if (x>T) x-=T;return x;}
    bool spfa()
    {
        memset(d,42,sizeof(d));d[S]=0;
        memset(flag,0,sizeof(flag));
        int head=0,tail=1;q[1]=S;
        do
        {
            int x=q[inc(head)];flag[x]=0;
            for (int i=p[x];~i;i=edge[i].nxt)
            if (d[x]+edge[i].cost<d[edge[i].to]&&edge[i].flow<edge[i].cap)
            {
                d[edge[i].to]=d[x]+edge[i].cost;
                pre[edge[i].to]=i;
                if (!flag[edge[i].to]) q[inc(tail)]=edge[i].to,flag[edge[i].to]=1;
            }
        }while (head!=tail);
        return d[T]<=10000000;
    }
    void ekspfa()
    {
        while (spfa())
        {
            int v=1;
            for (int i=T;i!=S;i=edge[pre[i]^1].to)
            if (edge[pre[i]].flow==edge[pre[i]].cap) {v=0;break;}
            if (v)
            for (int i=T;i!=S;i=edge[pre[i]^1].to)
            ans-=edge[pre[i]].cost,edge[pre[i]].flow++,edge[pre[i]^1].flow--;
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2597.in","r",stdin);
        freopen("bzoj2597.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        cnt=n=read();
        memset(p,255,sizeof(p));
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            {
                int x=read();
                if (i<j)
                {
                    cnt++;l[cnt]=i,r[cnt]=j;
                    addedge(S,cnt,1,0);
                    if (x==0) addedge(cnt,j,1,0);
                    else if (x==1) addedge(cnt,i,1,0);
                    else addedge(cnt,i,1,0),addedge(cnt,j,1,0);
                }
            }
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            addedge(i,T,1,j-1);
        ans=n*(n-1)*(n-2)/6;
        ekspfa();
        cout<<ans<<endl;
        for (int i=n+1;i<=cnt;i++)
            for (int j=p[i];~j;j=edge[j].nxt)
            if (edge[j].flow>0) 
                if (edge[j].to==l[i]) a[l[i]][r[i]]=1;else a[r[i]][l[i]]=1;
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=n;j++)
            printf("%d ",a[i][j]);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    去掉字幕文件里的时间轴信息
    Git常用命令笔记
    VMware machine里的文件
    C# Inventor二次开发—004—创建二维草图(2)
    C# Inventor二次开发—003—创建二维草图
    C# Inventor二次开发—002—启动Inventor及零部件创建和打开
    C# Inventor二次开发—001—准备工作
    UTF-8 BOM编码格式文件对SSI的影响
    滚动到顶部
    如何理解 “私有成员只有在声明它们的类和结构体中才是可访问的” ?
  • 原文地址:https://www.cnblogs.com/Gloid/p/9595597.html
Copyright © 2011-2022 走看看