3.議員祕密ios
(secret.pas/c/cpp)ide
【問題描述】url
某國有N個議員,大佬XDD要從中選出來一部分一塊兒喝茶談一些事情。某兩個議員之間可能存在矛盾,大佬XDD不但願選出來的這些議員之間有任何矛盾關係,以致於喝喝茶的場面搞得很尷尬。spa
已知這些議員之間存在M對矛盾關係,你可否幫助大佬XDD計算出他最多能夠選出多少個議員來喝茶談事情?code
若是聰明的你把議員當作點,把矛盾關係當作無向邊,那麼題目中的數據保證M對矛盾所構成的圖中不存在含有超過3個點的環。(圖1符合要求,圖2則不符合)blog
【輸入數據】ip
輸入文件的第一行是用空格隔開的兩個整數N和M,表示一共有N個議員,這些議員之間有M對矛盾關係。接下來的M行,每行將有一對整數a和b(用空格隔開),表示議員a與議員b有矛盾。輸入數據保證不含重邊和自環。(議員的編號都是從1開始的)ci
【輸出數據】get
輸出一行,包含一個整數,即大佬XDD最多能夠選出多少議員來喝茶談事情。input
【輸入輸出樣例】
secret.in
5 6
1 2
3 2
1 3
3 5
3 4
4 5
secret.out
2
【樣例說明】
某國有6個議員,矛盾關係中1 - 2 - 3組成一個環,3 - 4 - 5組成一個環,所以只能在這兩個環中分別選一個議員,而且不能選擇3號議員。
【數據規模與約定】
對於20%的數據,1 ≤ N ≤ 20
對於40%的數據,1 ≤ N ≤ 50
對於100%的數據,1 ≤ N ≤ 200
輸入數據保證合法。
————————————————————我是分割線————————————————————————
dp題目。聽說是樹狀(仙人掌???)。
dp[i][j]表示第i個點,選(j==1)或不選(j==0)的狀況。
注意題目沒有保證聯通,有多是森林。
寫的記憶化搜索,代碼以下:
1 /* 2 Problem: 3 OJ: 4 User: S.B.S. 5 Time: 6 Memory: 7 Length: 8 */ 9 #include<iostream> 10 #include<cstdio> 11 #include<cstring> 12 #include<cmath> 13 #include<algorithm> 14 #include<queue> 15 #include<cstdlib> 16 #include<iomanip> 17 #include<cassert> 18 #include<climits> 19 #include<functional> 20 #include<bitset> 21 #include<vector> 22 #include<list> 23 #define F(i,j,k) for(register int i=j;i<=k;++i) 24 #define M(a,b) memset(a,b,sizeof(a)) 25 #define FF(i,j,k) for(register int i=j;i>=k;i--) 26 #define maxn 210 27 #define inf 0x3f3f3f3f 28 #define maxm 4001 29 #define mod 998244353 30 #define LOCAL 31 using namespace std; 32 int read(){ 33 int x=0,f=1;char ch=getchar(); 34 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 35 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 36 return x*f; 37 } 38 int n,m; 39 int fa[maxn],dp[maxn][2]; 40 bool tree[maxn][maxn]; 41 bool vis[maxn],mp[maxn][maxn]; 42 inline void dfs(int u) 43 { 44 vis[u]=true; 45 F(i,1,n){ 46 if(!vis[i]&&mp[u][i]){ 47 tree[u][i]=1; 48 fa[i]=u; 49 dfs(i); 50 } 51 } 52 } 53 inline int solve(int u,int v) 54 { 55 int cnt; 56 if(dp[v][u]!=-1) return dp[v][u]; 57 if(u==0){ 58 cnt=0; 59 F(i,1,n) if(tree[v][i]) cnt+=max(solve(0,i),solve(1,i)); 60 return dp[v][u]=cnt; 61 } 62 else{ 63 bool temp[maxn];M(temp,0); 64 F(i,1,n){ 65 if(tree[v][i]){ 66 temp[i]=true; 67 F(j,1,n) if(tree[i][j]&&mp[v][j]) temp[j]=true; 68 } 69 } 70 cnt=0; 71 F(i,1,n) if(!temp[i]&&fa[i]!=-1&&temp[fa[i]]) 72 cnt+=max(solve(0,i),solve(1,i)); 73 return dp[v][u]=cnt+1; 74 } 75 } 76 int ans; 77 int main() 78 { 79 std::ios::sync_with_stdio(false);//cout<<setiosflags(ios::fixed)<<setprecision(1)<<y; 80 #ifdef LOCAL 81 freopen("input.txt","r",stdin); 82 freopen("output.txt","w",stdout); 83 #endif 84 cin>>n>>m; 85 M(dp,-1);M(fa,-1); 86 F(i,1,m){int a,b;cin>>a>>b;mp[a][b]=mp[b][a]=1;} 87 F(i,1,n){ 88 if(!vis[i]){ 89 dfs(i); 90 ans+=max(solve(0,i),solve(1,i)); 91 } 92 } 93 cout<<ans<<endl; 94 return 0; 95 }