Description
有一个拥有n个城市的国家。这个国家由n-1条边连接起来。有一天国家发生叛乱。叛军已占领了一些城市。如果叛军占领的城市中,存在两个城市之间有边直接相连,则称这种情况是坏的。现在并不知道叛军占领了那些城市,问有多少种情况是坏的?
Input
第1行一个正整数n,表示国家的大小
第2行到第n行,每行两个数字x, y,表示x,y之间有一条边。
Output
一个整数表示方案数,答案对(1e9+7)取模
Sample Input
2
1 2
Sample Output
1
HINT
1 <= n <= 1e5,1<=x,y<=n,x≠y
以下题解搬运自出题人yyl:“直接做dp应该也是可以的。但是补集转化之后,我们发现其实就是问从点集V中选出若干个点构成点集S,满足S是一个独立集(即S中任意两点没有边直接相连)。设方案数为x。答案就是2^n -x。”
补充:最后输出2^n -x时因为涉及取模,要注意处理负数的情况。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define ll long long 5 using namespace std; 6 const int N=1e5+5; 7 const int mod=1e9+7; 8 int n,x,y,cnt,head[N]; 9 struct edge{int to,next;}e[N*2]; 10 ll ansn=1,dp[N][2]; 11 int read() 12 { 13 int x=0,f=1;char c=getchar(); 14 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 15 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 16 return x*f; 17 } 18 void ins(int u,int v){cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;} 19 void solve(int x,int fa) 20 { 21 dp[x][1]=dp[x][0]=1; 22 for(int i=head[x];i;i=e[i].next) 23 { 24 int to=e[i].to; 25 if(to==fa)continue; 26 solve(to,x); 27 dp[x][0]=(dp[to][0]+dp[to][1])%mod*dp[x][0]%mod; 28 dp[x][1]=dp[to][0]*dp[x][1]%mod; 29 } 30 } 31 int main() 32 { 33 n=read(); 34 for(int i=1;i<n;i++) 35 { 36 x=read();y=read(); 37 ins(x,y);ins(y,x); 38 } 39 solve(1,0); 40 for(int i=1;i<=n;i++)ansn=(ansn*2)%mod; 41 printf("%lld",((ansn-dp[1][0]-dp[1][1])%mod+mod)%mod); 42 return 0; 43 }