bzoj1040基环树
。。。
st#include<cstdio>
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<vector> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 1e6+5; typedef long long ll; struct node { int to,next; } e[2*maxn]; //以这种方式建图,就不需要建树。 int head[maxn]; //可以随意取任何一个节点作为根节点,因为本来就是无向图 int ans = 0,cut,root,_root; int n; int w[maxn],vis[maxn]; ll dp[maxn][2]; //这种建图方式很好 void add(int u,int v) { //无向图,两边都要加 e[ans].to = v; //记录当前第ans根线的to e[ans].next=head[u]; //指向head[u] 之前指向的那根线。 head[u]=ans++; //指向当前线 } void dfs(int u,int fa){ //寻找环 ,顺便,标记vis vis[u] = 1; for(int i=head[u];i!=-1;i=e[i].next){ int v = e[i].to; if(v == fa) continue; if(!vis[v]) dfs(v,u); else {root = v;_root=u;cut=i;} //标记要待会作为根节点的root和 } //_root 以及拆掉的线i } void tree_dp(int u,int fa){ dp[u][1] = w[u]; dp[u][0] = 0; for(int i=head[u];i!=-1;i=e[i].next){ int temp = e[i].to; if(i == cut || i == (cut^1) || temp == fa) continue; //优先级的问题 如果当前线等于拆掉的线return tree_dp(temp,u); dp[u][1] += dp[temp][0]; dp[u][0] += max(dp[temp][1],dp[temp][0]); } } int main() { while(~scanf("%d",&n)) { ans = 0; memset(w,0,sizeof(w)); memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); memset(head,-1,sizeof(head)); for(int i=1; i<=n; i++) { int u; scanf("%d %d",&w[i],&u); add(i,u); add(u,i); } ll sum =0; for(int i=1;i<=n;i++){ if(vis[i]) continue; dfs(i,-1); // printf("%d %d %d\n",root,_root,cut); tree_dp(root,-1);//????(将-1改为_root就会wa) ll temp = dp[root][0]; tree_dp(_root,-1);///???为什么-1就ac,0就wa sum+=max(temp,dp[_root][0]); } printf("%lld\n",sum); } return 0; }
wa:
#include<cstdio> #include<cstring> #define LL long long using namespace std; const int maxn=1e6+5; inline LL max(LL a,LL b){return (a<b?b:a);} int first[maxn],next[maxn*2],to[maxn*2]; int edge_count=-1;//!!!!重点错误::因为每次两个边是连在一起的所以应该(0,1),(2,3)而不是(1,2),(2,3)【此处指的是边编号】 inline void add(int x,int y){ edge_count++; to[edge_count]=y; next[edge_count]=first[x]; first[x]=edge_count; } int n,a[maxn]; inline void read(int &a){ a=0;int b=1;char x=getchar(); while(x<'0' || '9'<x){ if(x=='-')b=-1; x=getchar(); } while('0'<=x && x<='9'){ a=(a<<3)+(a<<1)+x-'0'; x=getchar(); } a*=b; } bool vis[maxn]; int x[maxn],y[maxn],cnt[maxn],p; void dfs(int root,int fa){ vis[root]=1; for(int i=first[root];i!=-1;i=next[i]){ if(to[i]==fa)continue; if(vis [ to[i] ]){ x[p]=root; y[p]=to[i]; cnt[p]=i; } else dfs(to[i],root); } } LL f[maxn][2],ans; //1->选了 0->没选 void search(int root,int fa,int ban){ // printf("%d %d %d\n",root,fa,ban); f[root][1]=(LL)a[root]; f[root][0]=0ll; for(int i=first[root];i!=-1;i=next[i]){ if(to[i]==fa || i==ban || i==(ban^1) )continue; search(to[i],root,ban); f[root][1]+=f[ to[i] ][0]; f[root][0]+=max(f[ to[i] ][1],f[ to[i] ][0]); } } int main() { //freopen("knight.in","r",stdin); read(n); memset(first,-1,sizeof(first)); for(int i=1,en;i<=n;i++){ read(a[i]);read(en); add(i,en); add(en,i); } for(int i=1;i<=n;i++){ if(!vis[i]){ dfs(i,-1); // printf("%d %d\n",x[p],y[p]); p++; } } //memset(vis,0,sizeof(vis)); for(int i=0;i<p;i++){ LL temp=0ll; //memset(vis,0,sizeof(vis)); search(x[i],0,cnt[i]);
//(之前写的是:search(x[i],y[i],cnt[i]));也是wa temp=f[ x[i] ][0]; // memset(vis,0,sizeof(vis)); search(y[i],0,cnt[i]); //(只有写成search(y[i],-1,cnt[i]);才能对) ans+=max(temp,f[ y[i] ][0]); } printf("%lld",ans); return 0; }