P6033 Ryoku 的探索 (基环树)

题目链接

 

 题解:

图为一个基环树。

dfs找到环,对于环上的每一个点u, 确定与它连接的具有最小美观度的边的长度w, 把这个w值更新到与它连接的其他非环上点(minval[]数组),则u和与它连接的其他非环上点的答案即为所有边长度只和减去minval[i]。

 

Code:

  1 #include <bits/stdc++.h>
  2 # define LL long long
  3 using namespace std;
  4 
  5 const int maxn=1000000+10;
  6 const int INF=0x7fffffff;
  7 struct Edge{
  8     int v,next,w,p;
  9 }e[maxn<<1];
 10 int head[maxn];
 11 int en;
 12 
 13 int n;
 14 int incycle[maxn];
 15 int instack[maxn];
 16 stack<int> stk;
 17 bool hasfind;
 18 int minval[maxn];
 19 
 20 
 21 void add(int from, int to, int w, int p){
 22     e[en].v=to;
 23     e[en].next=head[from];
 24     e[en].w=w;
 25     e[en].p=p;
 26     head[from]=en;
 27     ++en;
 28 }
 29 
 30 void dfs(int u, int pre){
 31     if(hasfind) return;
 32     if(instack[u]==1){
 33         while(stk.top()!=u){
 34             int t=stk.top();
 35             stk.pop();
 36             incycle[t]=1;
 37             instack[t]=0;
 38         }
 39         stk.pop();
 40         instack[u]=0;
 41         incycle[u]=1;
 42         hasfind=true;
 43         return;
 44     }
 45     instack[u]=1;
 46     stk.push(u);
 47     for(int i=head[u];i!=-1;i=e[i].next){
 48         int v=e[i].v;
 49         if(v==pre) continue;
 50         dfs(v,u);
 51     }
 52     stk.pop();
 53     instack[u]=0;
 54 }
 55 
 56 void setvalue(int u, int val){
 57     minval[u]=val;
 58     for(int i=head[u];i!=-1;i=e[i].next){
 59         int to=e[i].v;
 60         if(incycle[to]==0 && minval[to]==-1){
 61             setvalue(to,val);
 62         }
 63     }
 64 }
 65 
 66 int main(){
 67     memset(head,-1,sizeof(head));
 68     memset(minval,-1,sizeof(minval));
 69     scanf("%d", &n);
 70     LL total=0;
 71     for(int i=1;i<=n;++i){
 72         int a,b,c,d;
 73         scanf("%d %d %d %d", &a, &b, &c, &d);
 74         total+=c;
 75         add(a,b,c,d);
 76         add(b,a,c,d);
 77     }
 78     hasfind=false;
 79     dfs(1,0);
 80 
 81     for(int i=1;i<=n;++i){
 82         if(incycle[i]==1){
 83             int minp=INF;
 84             int minw=0;
 85             for(int j=head[i];j!=-1;j=e[j].next){
 86                 int to=e[j].v;
 87                 if(incycle[to]==1){
 88                     if(e[j].p<minp){
 89                         minp=e[j].p;
 90                         minw=e[j].w;
 91                     }
 92                 }
 93             }
 94             setvalue(i,minw);
 95         }
 96     }
 97 
 98     for(int i=1;i<=n;++i){
 99         printf("%lld\n", total-minval[i]);
100     }
101     return 0;
102 }

 

posted @ 2020-01-31 19:49  feibilun  阅读(193)  评论(0编辑  收藏  举报