題目描述:
bzluogu
題解:最小費用流。
對於三支隊伍,勝負情況只有$2$種。
一種是形成三元環,另一種是$x$贏兩場,$y$贏一場,$z$沒贏過。
所以我們統計一下另一種最少有多少種就好了。
最後答案就是$c^3_n-k$。
對於乙個隊伍$x$,若其勝場數為$w_x$,則會造成的負貢獻為$-c^2_$。
不會搞?
作差啊。
$$c^2_x-c^2_=x-1$$
所以建圖:
$s$向每一場比賽對應的點建容量為$1$,費用為$0$的邊,表示只有一次貢獻。
討論比賽對隊伍的貢獻,若是$0$/$1$就向勝者建容量為$0$,費用為$1$的邊,不然向雙方都建容量$0$,費用$1$的邊。
所有隊伍向匯點建一堆邊,費用為$0,1,2,……,n-1$,容量都為$1$,表示加入此邊後的負貢獻。
結果發現會$t$。
原因很簡單:圖中有一堆邊是顯然的,我們可以直接算貢獻。
優化一下就能過了。
**:
#include#includeview code#include
#include
using
namespace
std;
typedef
long
long
ll;const
int inf = 0x3f3f3f3f
;const ll inf =0x3f3f3f3f3f3f3f3fll;
const
int n = 10500
;template
inline
void read(t&x)
while(ch>='
0'&&ch<='9')
x = f*c;
}int n,w[105][105],s,t,tot,hed[n],cnt=1,ind[105],nam[105][105
];struct
ege[n
<<4
];void ae(int f,int
t,ll fl,ll wl)
void ae(int f,int
t,ll fl,ll wl)
ll dep[n],fl[n];
intpre[n],fa[n];
bool
vis[n];
bool
spfa()}}
vis[u] = 0
; }
return dep[t] !=inf;
}ll mcmf()
}return
ret;
}int
main()
}for(int i=1;i<=n;i++)
for(int j=ind[i];j<=n;j++)
ae(i,t,
1,j);
ll ans = 1ll*n*(n-1)/2ll*(n-2)/3ll-mcmf();
for(int i=1;i<=n;i++)
ans -= 1ll*ind[i]*(ind[i]-1)/2ll;
printf(
"%lld\n
",ans);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)if(w[i][j]==2
)
for(int k=hed[nam[i][j]];k;k=e[k].nxt)
for(int i=1;i<=n;i++,puts(""
))
for(int j=1;j<=n;j++)
printf(
"%d
",w[i][j]);
return0;
}
WC2007 剪刀石頭布
正著求不太好求,但是不是剪刀石頭布的又很好表示 三個人中恰好有乙個人贏了兩場。所以我們考慮讓這種三元組數量最少使得剪刀石頭布最多。考慮乙個人如果贏了i場,那麼他對 非剪刀石頭布的三元組的貢獻是 i i 1 2 也就是他和任意兩個被他擊敗的人都可以組成三元組。並且每個人的貢獻都是獨立的,不會有重複 因...
WC2007 剪刀石頭布 Solution
給一張競賽圖,圖中還有一些邊沒有定向,現在要把它們重新定向,要求重定向之後三元環盡量多。直接考慮不可取,逆向思維。算出極限情況可能出現三元環的個數,那麼就是n n 1 n 2 6 dfrac 6n n 1 n 2 接下來考慮什麼情況會拆毀三元環。考慮乙個點的負場情況來判斷少了多少三元環。如果乙個點負...
Wc2007 剪刀石頭布(費用流)
time limit 20 sec memory limit 128 mb sec special judge 在一些一對一遊戲的比賽 如下棋 桌球和羽毛球的單打 中,我們經常會遇到a勝過b,b勝過c而c又勝過a的有趣情況,不妨形象的稱之為剪刀石頭布情況。有的時候,無聊的人們會津津樂道於統計有多少這...