首页 > 代码库 > 【SRM-05 B】无题?

【SRM-05 B】无题?

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 }
View Code

【SRM-05 B】无题?