洛古
一句話題意:給定一張圖,每兩點之間有一條有向邊或無向邊,把所有無向邊定向,使圖中三元環個數盡量多
因為原圖是乙個完全圖,假設圖中任意三點都能構成三元環,那麼途中三元環的個數為:\(\binom\)。
那麼如果乙個三元組不是三元環,那麼有乙個點的出度為2。
我們假設乙個點的出度為d,那麼對於這個點,三元環會減少\(\frac\)
所以三元環的數量為:\(\binom- \sum_^n\binom=\binom- \sum_^n\frac\)
所以我們要最小化:$ \sum_^n\frac$的值。
怎麼做呢?
如果我們對於一條無向邊,可能讓u出度+1,也可能讓v出度+1,非黑即白,所以我們可以考慮費用流。
觀察柿子\(\frac\),容(hen)易(nan)想到小學等差數列求和公式,於是我們可以將乙個點的貢獻看成\((0+1+2+3+……+d[i]-1)\)
把每一條邊看成乙個點,從源點向每條邊連一條容量為1,費用為0的邊。
對於一條無向邊,往u,v分別建一條容量為1,費用為0的邊。
有向邊則把邊和v建一條容量為1,費用為0的邊。
每個點向匯點連n條容量為1,費用為0-(n-1)遞增的邊,表示上面的等差數列(可以表示出任何出度的情況)
最後就是費用流的板子了
**如下:
#includeusing namespace std;
#define il inline
#define re register
#define inf 123456789
#define debug printf("now is line : %d\n",__line__)
il int read()
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return x*f;
}#define maxn 105
#define maxm 105*105
struct edge
e[maxm<<3];
int n,a[maxn][maxn],s,t,maxflow,cost,vis[maxm],dis[maxm],head[maxm],cnt=1,pa;
il void add(int u,int v,int val,int w)
; head[u]=cnt;
e[++cnt]=(edge);
head[v]=cnt;
}queueq;
il bool spfa()}}
}return dis[t]!=2139062143;
}il int dfs(int u,int mi)
vis[u]=1;
int use=0;
for(re int i=head[u];i;i=e[i].next)}}
return use;
}il void dinic()
}int ans=((n-1)*(n-2)*n)/6;
ans-=cost;
printf("%d\n",ans);
}int main()
else if(a[i][j]==1) add(s,n*n+j,1,0);
else add(s,n*n+i,1,0);}}
for(re int i=1;i<=n;++i)
dinic();
for(re int i=1;i<=n;++i)}}
}for(re int i=1;i<=n;++i,puts(""))
return 0;
}
Wc2007 剪刀石頭布
題目描述 bzluogu 題解 最小費用流。對於三支隊伍,勝負情況只有 2 種。一種是形成三元環,另一種是 x 贏兩場,y 贏一場,z 沒贏過。所以我們統計一下另一種最少有多少種就好了。最後答案就是 c 3 n k 對於乙個隊伍 x 若其勝場數為 w x 則會造成的負貢獻為 c 2 不會搞?作差啊。...
WC2007 剪刀石頭布
正著求不太好求,但是不是剪刀石頭布的又很好表示 三個人中恰好有乙個人贏了兩場。所以我們考慮讓這種三元組數量最少使得剪刀石頭布最多。考慮乙個人如果贏了i場,那麼他對 非剪刀石頭布的三元組的貢獻是 i i 1 2 也就是他和任意兩個被他擊敗的人都可以組成三元組。並且每個人的貢獻都是獨立的,不會有重複 因...
WC2007 剪刀石頭布 Solution
給一張競賽圖,圖中還有一些邊沒有定向,現在要把它們重新定向,要求重定向之後三元環盡量多。直接考慮不可取,逆向思維。算出極限情況可能出現三元環的個數,那麼就是n n 1 n 2 6 dfrac 6n n 1 n 2 接下來考慮什麼情況會拆毀三元環。考慮乙個點的負場情況來判斷少了多少三元環。如果乙個點負...