题意:给定一个森林。每个节点上安装一个灯可以覆盖与该节点相连的所有边。选择最少的节点数num覆盖所有的边。在num最小的前提下,合理放置num个灯使得被两个灯覆盖的边最多?
思路:F[i][0]代表没放灯,F[i][1]代表放了灯,G[i]类似。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int f[1005][2],g[1005][2]; 7 int tot,go[200005],first[200005],next[200005]; 8 int n,m; 9 int read(){ 10 char ch=getchar();int t=0,f=1; 11 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();} 12 while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();} 13 return t*f; 14 } 15 void insert(int x,int y){ 16 tot++; 17 go[tot]=y; 18 next[tot]=first[x]; 19 first[x]=tot; 20 } 21 void add(int x,int y){ 22 insert(x,y);insert(y,x); 23 } 24 void dfs(int x,int fa){ 25 f[x][0]=0;g[x][0]=0; 26 f[x][1]=1;g[x][1]=0; 27 for (int i=first[x];i;i=next[i]){ 28 int pur=go[i]; 29 if (pur==fa) continue; 30 dfs(pur,x); 31 if (f[pur][0]<f[pur][1]||(f[pur][0]==f[pur][1]&&g[pur][0]>g[pur][1]+1)){ 32 f[x][1]+=f[pur][0]; 33 g[x][1]+=g[pur][0]; 34 }else{ 35 f[x][1]+=f[pur][1]; 36 g[x][1]+=g[pur][1]+1; 37 } 38 f[x][0]+=f[pur][1]; 39 g[x][0]+=g[pur][1]; 40 } 41 } 42 int main(){ 43 int T; 44 scanf("%d",&T); 45 for (int Tcase=1;Tcase<=T;Tcase++){ 46 n=read();m=read(); 47 tot=0; 48 for (int i=1;i<=n;i++) first[i]=g[i][0]=g[i][1]=0,f[i][0]=f[i][1]=-1; 49 for (int i=1;i<=m;i++){ 50 int x=read(),y=read(); 51 x++;y++; 52 add(x,y); 53 } 54 int ans1=0,ans2=0; 55 for (int i=1;i<=n;i++) 56 if (f[i][0]==-1&&f[i][1]==-1){ 57 dfs(i,0); 58 if (f[i][0]<f[i][1]||(f[i][0]==f[i][1]&&g[i][0]>g[i][1])){ 59 ans1+=f[i][0]; 60 ans2+=g[i][0]; 61 }else{ 62 ans1+=f[i][1]; 63 ans2+=g[i][1]; 64 } 65 } 66 printf("Case %d: %d %d %d\n",Tcase,ans1,ans2,m-ans2); 67 } 68 }
时间: 2024-11-06 13:48:53