zoukankan      html  css  js  c++  java
  • [PA2014]Budowa

    [PA2014]Budowa

    题目大意:

    有A和B两名候选人。共有(n(nle1000))个人参加投票。他们之间形成了一个树结构,树上的结点有两种身份:专家(叶子结点)或领导(非叶子结点)。每位专家都有自己的选择——支持A和B之中的一个;每位领导都有若干个下属(子结点),领导的选择决定于下属中人数较多的那一方,下属的数目保证为奇数,从而不会出现平局状况。最后,根结点的选择即为选举结果。

    目前仍有一些专家处于犹豫未决的状态,只要前去游说,就可获得他的支持。每人每天只能选择游说一名专家。A先开始,两人交替进行,直到每位专家都有了确定的选择。请问A是否有策略保证自己赢得选举胜利?

    思路:

    首先,假设那些犹豫的专家最后两边都不支持,如果此时已经B占优势,那么A永远没有反超的机会了。

    否则枚举每个犹豫的专家,令他支持A,剩下两边都不支持,看一下是否能使A胜利,如果能,就说明第一步可以选择这个专家。

    枚举复杂度(mathcal O(n)),计算支持者的复杂度(mathcal O(n)),总时间复杂度(mathcal O(n^2))。可以通过此题。

    实际上,本题还有一种(mathcal O(nlog n))的做法。

    一开始判断是否有解的算法同上,但是可以(mathcal O(n))求出可以选择的专家。

    对于一个点(x),若子结点中支持A的人数+(lceilfrac{ ext{犹豫的人数}}2 ceilge)支持B的人数,则说明可以选择该子树内的专家。

    由于要排序,所以时间复杂度是(mathcal O(nlog n))的。

    源代码:

    (mathcal O(n^2))

    #include<cstdio>
    #include<cctype>
    #include<vector>
    inline int getint() {
    	register char ch;
    	register bool neg=false;
    	while(!isdigit(ch=getchar())) neg|=ch=='-';
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return neg?-x:x;
    }
    const int N=1001;
    int c[N],d[N][2],ans[N];
    std::vector<int> e[N];
    inline void add_edge(const int &u,const int &v) {
    	e[u].push_back(v);
    }
    void dfs(const int &x,const int &par) {
    	//0: xyw, 1: jry
    	d[x][0]=d[x][1]=0;
    	if(c[x]<0) d[x][c[x]+2]++;
    	for(int i=0;i<c[x];i++) {
    		const int &y=e[x][i];
    		if(y==par) continue;
    		dfs(y,x);
    		if(d[y][1]==d[y][0]) continue;
    		d[x][d[y][1]>d[y][0]]++;
    	}
    }
    int main() {
    	const int n=getint();
    	for(register int i=1;i<=n;i++) {
    		c[i]=getint();
    		for(register int j=0;j<c[i];j++) {
    			add_edge(i,getint());
    		}
    	}
    	dfs(1,0);
    	if(d[1][1]>d[1][0]) {
    		puts("NIE");
    		return 0;
    	}
    	for(register int i=1;i<=n;i++) {
    		if(c[i]==0) {
    			c[i]=-2;
    			dfs(1,0);
    			if(d[1][0]>d[1][1]) {
    				ans[++ans[0]]=i;
    			}
    			c[i]=0;
    		}
    	}
    	printf("TAK %d
    ",ans[0]);
    	for(register int i=1;i<=ans[0];i++) {
    		printf("%d%c",ans[i]," 
    "[i==ans[0]]);
    	}
    	return 0;
    }
    

    (mathcal O(nlog n))

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<algorithm>
    inline int getint() {
    	register char ch;
    	register bool neg=false;
    	while(!isdigit(ch=getchar())) neg|=ch=='-';
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return neg?-x:x;
    }
    const int N=1001;
    int c[N],d[N][3],ans[N];
    std::vector<int> e[N];
    inline void add_edge(const int &u,const int &v) {
    	e[u].push_back(v);
    }
    void dfs(const int &x,const int &par) {
    	//0: xyw, 1: jry
    	if(c[x]<=0) d[x][c[x]+2]++;
    	for(int i=0;i<c[x];i++) {
    		const int &y=e[x][i];
    		if(y==par) continue;
    		dfs(y,x);
    		if(d[y][1]==d[y][0]) {
    			d[x][2]++;
    		} else {
    			d[x][d[y][1]>d[y][0]]++;
    		}
    	}
    }
    void solve(const int &x,const int &par) {
    	if(c[x]==0) ans[++ans[0]]=x;
    	for(int i=0;i<c[x];i++) {
    		const int &y=e[x][i];
    		if(y==par) continue;
    		if(d[y][0]+1-d[y][2]%2==d[y][1]) {
    			solve(y,x);
    		}
    	}
    }
    int main() {
    	const int n=getint();
    	for(register int i=1;i<=n;i++) {
    		c[i]=getint();
    		for(register int j=0;j<c[i];j++) {
    			add_edge(i,getint());
    		}
    	}
    	dfs(1,0);
    	if(d[1][1]>d[1][0]) {
    		puts("NIE");
    		return 0;
    	}
    	if(d[1][1]<d[1][0]) {
    		for(register int i=1;i<=n;i++) {
    			if(c[i]==0) {
    				ans[++ans[0]]=i;
    			}
    		}
    	} else {
    		solve(1,0);
    		std::sort(&ans[1],&ans[ans[0]]+1);
    	}
    	printf("TAK %d
    ",ans[0]);
    	for(register int i=1;i<=ans[0];i++) {
    		printf("%d%c",ans[i]," 
    "[i==ans[0]]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    芯片难题
    permutation
    小凸玩矩阵
    gender
    NOI2019序列非启发式做法
    莫比乌斯函数&莫比乌斯反演
    「雅礼day2」最大公约数gcd
    容斥原理&反演
    树上路径的交和并
    CF906D Power Tower
  • 原文地址:https://www.cnblogs.com/skylee03/p/10209043.html
Copyright © 2011-2022 走看看