1. 程式人生 > >汕頭市隊賽 yyl杯1 T2

汕頭市隊賽 yyl杯1 T2

tex namespace srm int pan print 解釋 spa 接下來

B SRM 05 - YYL 杯 R1

背景&&描述

有一個擁有n個城市的國家。這個國家由n-1條邊連接起來。有一天國家發生叛亂。叛軍已占領了一些城市。如果叛軍占領的城市中,存在兩個城市之間有邊直接相連,則稱這種情況是壞的。現在並不知道叛軍占領了那些城市,問有多少種情況是壞的?

輸入格式

第1行一個正整數n,表示國家的大小

第2行到第n行,每行兩個數字x, y,表示x,y之間有一條邊。

輸出格式

一個整數表示方案數,答案對(1e9+7)取模

樣例輸入

2

1 2

樣例輸出

1

數據範圍與約定

  • 對於0%的數據,和樣例一毛一樣。
  • 對於前20%的數據,技術分享
  • 對於接下來10%的數據,保證給出的是一條鏈,且 1 <= n <= 1e5
  • 對於接下來20%的數據,保證只有一個點的度數技術分享,其他點度數技術分享,且 1 <= n <= 1e5
  • 對於接下來20%的數據,保證給出的是一棵滿二叉樹,且 1 <= n <= 1e5
  • 對於剩下的數據,1 <= n <= 1e5,技術分享

樣例解釋

只有1和2同時叛變時才滿足題意。

這道題往補集上考慮會容易很多 所有的情況當然一共有2^n種 我們只要算出從點集V中選出若幹個點構成點集S,滿足S是一個獨立集(即S中任意兩點沒有邊直接相連)中S的數量x

答案就是2^n-x了 果然轉換很重要

技術分享
#include<cstdio>
#include<cstring>
#include
<algorithm> #define LL long long using namespace std; const int M=1e5+7,mod=1e9+7; int read(){ int ans=0,f=1,c=getchar(); while(c<0||c>9){if(c==-) f=-1; c=getchar();} while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();} return ans*f; } int n,first[M],cnt; LL f[M][
2],ans=1; struct node{int to,next;}e[2*M]; void ins(int a,int b){cnt++; e[cnt].to=b; e[cnt].next=first[a]; first[a]=cnt;} void insert(int a,int b){ins(a,b); ins(b,a);} void dp(int x,int last){ f[x][0]=f[x][1]=1; for(int i=first[x];i;i=e[i].next){ int now=e[i].to; if(now==last) continue; dp(now,x); f[x][0]=(f[now][0]+f[now][1])%mod*f[x][0]%mod; f[x][1]=f[now][0]*f[x][1]%mod; } } int main() { int x,y; n=read(); for(int i=1;i<n;i++) x=read(),y=read(),insert(x,y); dp(1,0); for(int i=1;i<=n;i++) ans=ans*2%mod; printf("%lld\n",((ans-f[1][0]-f[1][1])%mod+mod)%mod); return 0; }
View Code

汕頭市隊賽 yyl杯1 T2