日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2019年湘潭大学程序设计竞赛(重现赛)F.Truthman or Fakeman(并查集)

發(fā)布時(shí)間:2024/9/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2019年湘潭大学程序设计竞赛(重现赛)F.Truthman or Fakeman(并查集) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

鏈接:https://ac.nowcoder.com/acm/problem/25579
來源:??途W(wǎng)

時(shí)間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
Special Judge, 64bit IO Format: %lld
題目描述
有n個(gè)人在玩一個(gè)身份扮演的游戲。
把這n個(gè)人編號(hào)為1,2,3…n。
其中每個(gè)人會(huì)扮演下面兩種身份中的一種:
Truthman:當(dāng)某個(gè)人扮演Truthman時(shí),這個(gè)人只會(huì)說真話。
Fakeman:當(dāng)某個(gè)人扮演Fakeman時(shí),這個(gè)人只會(huì)說假話。
這n個(gè)人是互相知道身份的,但是Casya作為一個(gè)旁觀者不知道任何一個(gè)人的身份。
為了讓Casya有可能推斷這些人的身份,這n個(gè)人說了m句話。
每句話的內(nèi)容只包含某人對(duì)某人身份的一條描述,且被Casya記錄為以下形式:
u,v,0 – u認(rèn)為v是一個(gè)Fakeman;
u,v,1 – u認(rèn)為v是一個(gè)Truthman;
當(dāng)然這些話不一定都是真話,這取決于說話的人的身份。
但是可以肯定的是身份只有兩種,也就是說某個(gè)人不是Truthman就是Fakeman。

Casya想知道不違反上面的條件和記錄最少有多少個(gè)Fakeman,除此之外他還想得到一組在此情況下的一組合理的解—即所有人的身份?;蛘叽_定記錄本來就是矛盾的所以沒有任何符合條件的解。
輸入描述:
第一行一個(gè)數(shù)字T(1≤T≤30)–樣例個(gè)數(shù)。
其中每個(gè)樣例:
第一行兩個(gè)數(shù)字n,m(1≤n≤1e5 )。
然后m行,每一行包含三個(gè)整數(shù)u,v,w(1≤u,v≤n,w={0,1})
保證所有樣例中\(zhòng)sum n∑n不超過2×1e6 。
保證所有樣例中\(zhòng)sum m∑m不超過2×1e6。
輸出描述:
每個(gè)樣例輸出一行。
如果存在合理的解,輸出一個(gè)長度為n的字符串,且只包含’0’或’1’。
其中第i個(gè)字符為’0’表示iii是一個(gè)Fakeman,為’1’表示i是一個(gè)Truthman。并使得Fakeman的數(shù)量最少。如果有多個(gè)解符合要求,輸出任意一個(gè)即可。

如果不存在任何合理的解,輸出-1。
示例1
輸入
復(fù)制

2 5 4 1 2 1 2 3 0 2 4 0 1 5 0 3 3 1 2 1 1 3 0 2 3 1

輸出
復(fù)制

00111 -1

/*
當(dāng)然這些話不一定都是真話,這取決于說話的人的身份。
當(dāng)u說v是truthman,(u,v,w = 1)時(shí),u,v一定是同一陣營的,要么都truth,要么都fake。
而u說v是fakeman,(u,v, w = 0)時(shí),u,v一定是不同陣營的。
此時(shí)我們需要?jiǎng)澐殖鰞蓚€(gè)集合,一個(gè)truthman,另一個(gè)fakeman,
這兩個(gè)集合中哪個(gè)是truthman集合取決于哪個(gè)集合人數(shù)更多,因?yàn)檫@兩個(gè)集合一定互斥,
題目要求最少的fakeman,反之更多的truthman。
一個(gè)人的身份開始不確定,本題處理方式:原編號(hào)+n作為另一種可能身份的編號(hào)。
本題有可能某些人是沒有被描述到的,由于初始化集合操作,
最初每個(gè)人只屬于一個(gè)小集合,此時(shí)到最后可以統(tǒng)一處理,
哪個(gè)集合人數(shù)多就歸到哪個(gè)集合去。
-1的情況:
查一個(gè)人的根,當(dāng)一個(gè)人的根有兩種身份的時(shí)候,直接輸出-1即可
*/
Ac_code:

#include <stdio.h> const int MAXN = 1e5+5; int pre[MAXN<<1]; int cnt[MAXN<<1]; int vis[MAXN<<1]; int n,m; void init() {for(int i = 1; i <= (n<<1); i++){vis[i] = 0;pre[i] = i;cnt[i] = (i<=n);} } int myFind(int x) {return x == pre[x] ? x : pre[x] = myFind(pre[x]); } void myUnion(int x,int y) {int fx = myFind(x);int fy = myFind(y);if(fx != fy){pre[fx] = fy;cnt[fy] += cnt[fx];} } void solve() {for(int i = 1; i <= n; i++){int x = myFind(i);int y = myFind(i+n);if(x == y){puts("-1");return;}if(vis[x] == 0)//集合未確定{//哪個(gè)集合人數(shù)多就歸為truthman,vis標(biāo)記為1if(cnt[x] > cnt[y]){vis[x] = 1;vis[y] = -1;}else{vis[y] = 1;vis[x] = -1;}}}for(int i = 1; i <= n; i++){if(vis[myFind(i)] == 1)printf("1");elseprintf("0");}puts("");return; } int main() {int T;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);init();int u,v,w;for(int i = 0; i < m; i++){scanf("%d%d%d",&u,&v,&w);if(w){//兩個(gè)人是相同身份myUnion(u,v);myUnion(u+n,v+n);}else{//兩個(gè)人是不同身份myUnion(u,v+n);myUnion(u+n,v);}}solve();}return 0; }

總結(jié)

以上是生活随笔為你收集整理的2019年湘潭大学程序设计竞赛(重现赛)F.Truthman or Fakeman(并查集)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。