我哭啊……这题在考试的时候(我不是山东的,CH大法吼)没想出来……只写了50分的暴力QAQ
而且苦逼的写的比正解还长……我骗点分容易吗QAQ
骗分做法:
1.$n,m\leq 1000$: 直接找一个关键点做根进行深搜,算出其他关键点都与root连通的最小边权和,再×2
2.一条链的情况:用set维护序列中哪些点选了,然后ans=(sum[tail]-sum[head])*2; 其中sum[i]表示从序列首到第 i 个的边长之和……嗯就是前缀和优化一下= =取首和尾这一段的Len之和
3.保证第一次一定变动1号村庄,且以后1不再变动:以1为根,每次update(x),将从x到1的所有边更新一遍,看有多少个点需要经过它,如果是新加的边就在ans中加进来,如果这次删点后这条边无用了,就在ans中减去
以上就是50分的骗分做法……写起来倒是不难(正解写起来更简单QAQ)
1 //Huce #4 B 2 #include<set> 3 #include<vector> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define rep(i,n) for(int i=0;i<n;++i) 10 #define F(i,j,n) for(int i=j;i<=n;++i) 11 #define D(i,j,n) for(int i=j;i>=n;--i) 12 using namespace std; 13 14 int getint(){ 15 int v=0,sign=1; char ch=getchar(); 16 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 17 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 18 return v*sign; 19 } 20 typedef long long LL; 21 const int N=100010,INF=~0u>>2; 22 /*******************tamplate********************/ 23 int head[N],to[N<<1],next[N<<1],len[N<<1],cnt; 24 void add(int x,int y,int z){ 25 to[++cnt]=y; next[cnt]=head[x]; len[cnt]=z; head[x]=cnt; 26 to[++cnt]=x; next[cnt]=head[y]; len[cnt]=z; head[y]=cnt; 27 } 28 /*********************edge**********************/ 29 int n,m,du[N]; 30 bool sign[N],vis[N]; 31 32 namespace work1{ 33 LL ans; 34 bool dfs(int x){ 35 bool tmp=sign[x]; 36 vis[x]=1; 37 for(int i=head[x];i;i=next[i]) if(!vis[to[i]]){ 38 if (dfs(to[i])){ 39 ans+=len[i]; 40 tmp=1; 41 } 42 } 43 return tmp; 44 } 45 LL solve(){ 46 ans=0; 47 memset(vis,0,sizeof vis); 48 F(i,1,n) if (sign[i]){ 49 dfs(i); 50 return ans; 51 } 52 } 53 void work1(){ 54 int x; 55 F(i,1,m){ 56 x=getint(); sign[x]^=1; 57 printf("%lld\n",solve()*2); 58 } 59 } 60 } 61 namespace work2{ 62 int a[N],tot,num[N]; 63 LL sum[N]; 64 void dfs(int x,int l){ 65 vis[x]=1; 66 a[++tot]=x; 67 sum[tot]=sum[tot-1]+l; 68 num[x]=tot; 69 for(int i=head[x];i;i=next[i]) 70 if (!vis[to[i]]) 71 dfs(to[i],len[i]); 72 } 73 set<int>s; 74 set<int>::iterator it; 75 void work2(){ 76 F(i,1,n) if (du[i]==1){ 77 dfs(i,0); 78 break; 79 } 80 // F(i,1,tot) printf("%d ",a[i]);puts(""); 81 int x; 82 F(i,1,m){ 83 x=getint(); 84 sign[x]^=1; 85 if (sign[x]) s.insert(num[x]); 86 else{ 87 it=s.find(num[x]); 88 s.erase(it); 89 } 90 it=s.end(); it--; 91 // printf("%d %d\n",*s.begin(),*s.rbegin()); 92 printf("%lld\n",(sum[*s.rbegin()]-sum[*s.begin()])*2); 93 } 94 } 95 } 96 namespace work3{ 97 int fa[N],num[N],dis[N]; 98 LL ans; 99 bool vis[N]; 100 void dfs(int x){ 101 vis[x]=1; 102 for(int i=head[x];i;i=next[i]) 103 if (!vis[to[i]]){ 104 fa[to[i]]=x; 105 dis[to[i]]=len[i]; 106 dfs(to[i]); 107 } 108 } 109 void update(int x,int v){ 110 if (x==1) return; 111 if (v==1){ 112 num[x]++; 113 if (num[x]==1) ans+=dis[x]; 114 }else{ 115 num[x]--; 116 if (num[x]==0) ans-=dis[x]; 117 } 118 update(fa[x],v); 119 } 120 void work3(){ 121 int x; 122 memset(vis,0,sizeof vis); 123 dfs(1); 124 // F(i,1,n) printf("%d ",dis[i]); puts(""); 125 F(i,1,m){ 126 x=getint(); sign[x]^=1; 127 update(x,sign[x]?1:-1); 128 printf("%lld\n",ans*2); 129 } 130 } 131 } 132 int main(){ 133 #ifndef ONLINE_JUDGE 134 freopen("B.in","r",stdin); 135 // freopen("output.txt","w",stdout); 136 #endif 137 n=getint(); m=getint(); 138 int x,y,z,mx=0; 139 F(i,2,n){ 140 x=getint(); y=getint(); z=getint(); 141 add(x,y,z); 142 du[x]++; du[y]++; 143 mx=max(mx,max(du[x],du[y])); 144 } 145 if (n<=1000) work1::work1(); 146 else if (mx==2) work2::work2(); 147 else 148 work3::work3(); 149 return 0; 150 }