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;
    }
    
  • 相关阅读:
    HDU4366 Successor 线段树+预处理
    POJ2823 Sliding Window 单调队列
    HDU寻找最大值 递推求连续区间
    UVA846 Steps 二分查找
    HDU3415 Max Sum of MaxKsubsequence 单调队列
    HDU时间挑战 树状数组
    UVA10168 Summation of Four Primes 哥德巴赫猜想
    UESTC我要长高 DP优化
    HDUChess 递推
    HDU4362 Dragon Ball DP+优化
  • 原文地址:https://www.cnblogs.com/skylee03/p/10209043.html
Copyright © 2011-2022 走看看