P4249 [WC2007] rock paper scissors

The meaning of problems

God is really the question.

Questions required the largest number of three-membered ring, you may wish to consider the opposite of. We start \ (n-\) number which is selected from \ (3 \) a, there are \ (C_n ^ 3 \) kinds of programs that we considered after a minimum of a few selected not constitute a three-membered ring.

Consider the case of the three points do not constitute the three-membered ring, from the viewpoint of the degree of penetration and out, must be a point and the degree of admission are \ (1 \) , the degree of a point \ (2 \) an degree \ (0 \) , the degree of a point \ (2 \) into a degree \ (0 \) .

Thus from the viewpoint of penetration. If there is a point of the \ (2 \) , it will lose a three-membered ring, i.e., it is connected to its two points of this embodiment. If the degree of a point \ (3 \) , then it will lose the three three-membered ring, i.e. all its programs and it is connected to three selected points of the two.

So we know that: if a point \ (I \) is the degree of \ (D_i \) , then it will lose \ (C_ {d_i} ^ 2 \) a three-membered ring.

We give all sides are oriented not directed, if we directed a side \ (u-> v \) , so \ (v \) of the degree will add \ (1 \) , we set \ (v \) original the degree of the \ (D_v \) , consideration will be lost if this edge much three-membered ring, known as \ (. 1 + C_ {D_v} ^ 2-D_v C_ {2} = D_v ^ \) .

So we can give a calculated increase-degree point \ (1 \) Consideration generated, we want the minimum total cost thus can be obtained as follows built FIG Method:

1. From \ (S \) is connected to each of the non-oriented edge \ ((1,0) \) side.
2. Set the current section \ (X \) penetration points as \ (D_X \) , from each point \ (X \) is connected to the sink \ ((1, d_x), (1, d_x + 1) ... (1, n-2) \) edges, thus expressed \ (X \) increase the penetration \ (1 \) costs incurred.
3. For each non-oriented edge \ ((U, V) \) , from the side to \ (u, v \) are connected \ ((1,0) \) side.

After running the minimum cost maximum flow output 3. Proposal to determine whether the class side full flow can be.

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
const int maxm=10010;
const int inf=1e9;
int n,m,cnt_edge=1,S,T,ans;
int head[maxn+maxm],in[maxn],dis[maxm+maxn];
int a[maxn][maxn],pos[maxn][maxn];
bool vis[maxn+maxm];
struct Edge{int u,v;}E[maxm];
struct edge{int to,nxt,flow,cost;}e[maxm*4+maxn*maxn*2];
inline int read()
{
    char c=getchar();int res=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    return res*f;
}
inline void add(int u,int v,int w,int c)
{
    e[++cnt_edge].nxt=head[u];
    head[u]=cnt_edge;
    e[cnt_edge].to=v;
    e[cnt_edge].flow=w;
    e[cnt_edge].cost=c;
}
inline void addflow(int u,int v,int w,int c){add(u,v,w,c);add(v,u,0,-c);}
inline bool spfa()
{
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    deque<int>q;
    q.push_front(S);dis[S]=0;vis[S]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop_front();vis[x]=0;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(dis[y]>dis[x]+e[i].cost&&e[i].flow>0)
            {
                dis[y]=dis[x]+e[i].cost;
                if(!vis[y])
                {
                    if(q.empty()||dis[y]>dis[q.front()])q.push_back(y);
                    else q.push_front(y);
                    vis[y]=1;
                }
            }
        }
    }
    return dis[T]!=0x3f3f3f3f;
}
int dfs(int x,int lim)
{
    vis[x]=1;
    if(x==T||lim<=0)return lim;
    int res=lim;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to;
        if(dis[y]!=dis[x]+e[i].cost||e[i].flow<=0||vis[y])continue;
        int tmp=dfs(y,min(res,e[i].flow));
        res-=tmp;
        e[i].flow-=tmp,e[i^1].flow+=tmp;
        if(res<=0)break;
    }
    return lim-res;
}
inline int Dinic()
{
    int res=0,cost=0;
    while(spfa())
    {
        int flow=dfs(S,inf);
        while(flow>0)
        {
            res+=flow,cost+=flow*dis[T];
            memset(vis,0,sizeof(vis));
            flow=dfs(S,inf);
        }
    }
    return cost;
}
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    n=read();ans=n*(n-1)*(n-2)/6;
    for(int i=1;i<=n;i++)   
        for(int j=1;j<=n;j++)
        {
            a[i][j]=read();
            if(a[i][j]==1)in[j]++;
        }
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(a[i][j]!=2)continue;
            E[++m]=(Edge){i,j};
        }
    S=0,T=n+m+1;
    for(int i=1;i<=m;i++)
    {
        addflow(S,i,1,0);
        addflow(i,E[i].v+m,1,0);pos[E[i].u][E[i].v]=cnt_edge;
        addflow(i,E[i].u+m,1,0);pos[E[i].v][E[i].u]=cnt_edge;
    }
    for(int i=1;i<=n;i++)
    {
        ans-=in[i]*(in[i]-1)/2;
        for(int j=in[i]+1;j<n;j++)addflow(i+m,T,1,j-1);
    }
    printf("%d\n",ans-Dinic());
    for(int i=1;i<=n;i++,puts(""))
        for(int j=1;j<=n;j++)
        {
            if(a[i][j]<2)printf("%d ",a[i][j]);
            else printf("%d ",e[pos[i][j]].flow);
        }
    return 0;
}

Guess you like

Origin www.cnblogs.com/nofind/p/12115384.html