嘟嘟嘟
看資料範圍,加上題中頻繁提到的衝突,就可以想到演算法是最小割。
1.同意睡覺的,源點就像他連一條容量為1的邊。割掉它就代表他背叛了自己的意願。
2.同理,不同意睡覺的,就像匯點連一條邊。
3.考慮每一對朋友。如果兩個朋友意見相反,就互相連一條容量為1的邊,割掉其中的任意一條就代表朋友之間發生了衝突,代價為1.而且根據網路流性質,一定不會同時割掉這兩條邊。
4.如果一對朋友之間意見相同呢?其實還是建邊還是和上面一樣。因為如果割掉這條邊的原因一定是其中乙個人為了照顧和自己意見相反的其他朋友,而和這個朋友發生了衝突。
畫乙個圖:
1,2同意睡覺,且是朋友;3,4不同意睡覺;並且1和3,1和4還是朋友。
最小割為2,可以有這麼幾個典型情況:
1.割掉邊(6), (7):3和4為了照顧1,變卦了。
2.割掉邊(4), (5):1分別和3, 4發生衝突。
3.割掉邊(1), (3):1為了照顧3和4,變卦了,因此與2發生了衝突。
放**啦:
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11view codeusing
namespace
std;
12#define enter puts("")
13#define space putchar(' ')
14#define mem(a, x) memset(a, x, sizeof(a))
15#define rg register
16 typedef long
long
ll;17 typedef double
db;18
const
int inf = 0x3f3f3f3f;19
const db eps = 1e-8;20
const
int maxn = 305;21
inline ll read()
2226
while(isdigit(ch))
27if(last == '
-') ans = -ans;
28return
ans;29}
30 inline void
write(ll x)
3136
37int
n, m, t;
3839
struct
edge40;
43 vectoredges;
44 vectorg[maxn];
45void addedge(int
from, int
to)46
);48 edges.push_back((edge));
49int sz =edges.size();
50 g[from].push_back(sz - 2
);51 g[to].push_back(sz - 1
);52}53
54int
dis[maxn];
55bool
bfs()
5670}71
}72//for(int i = 1; i <= n; ++i) printf("%d ", dis[t]); enter;
73return
dis[t];74}
75int
cur[maxn];
76int dfs(int now, int
res)
7790}91
return
flow;92}
9394
intmincut()
95102
return
flow;
103}
104105
intmain()
106115
for(int i = 1; i <= m; ++i)
116120
write(mincut()); enter;
121return0;
122 }
SHOI2007 善意的投票
這個題一開始看到資料範圍和只能選0或者1的時候,直接就想到了網路流.可是想到費用流上了。但是之後發現這個題並不能用費用流做。因為雖然代價可以轉化成費用,但是流量並不是可以確定限制的。先把圖轉化成二分圖 s連選0的,1連t。乙個人只能有兩種選擇,選了乙個另外乙個就不需要付出代價了 最小割。我們用流量表...
SHOI 2007 善意的投票
題目鏈結 演算法 首先 選擇睡覺的人和不選擇睡覺的人構成兩個集合 這啟發我們用最小割解決該問題 1.將源點與每個睡覺的人連邊 將每個不睡覺的人與匯點連邊 割掉這樣的一條邊的含義是 有乙個人放棄了睡覺 不睡覺 產生了1衝突 2.將朋友之間連邊 割掉這樣一條邊的含義是 這兩個人產生了衝突 求解這個圖的最...
P2057 SHOI2007 善意的投票
題目描述 幼兒園裡有n個小朋友打算通過投票來決定睡不睡午覺。對他們來說,這個問題並不是很重要,於是他們決定發揚謙讓精神。雖然每個人都有自己的主見,但是為了照顧一下自己朋友的想法,他們也可以投和自己本來意願相反的票。我們定義一次投票的衝突數為好朋友之間發生衝突的總數加上和所有和自己本來意願發生衝突的人...