• hdu 4694 支配树


    支配树裸题:求支配集

    不太会写带权并查集,调了好久

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 using namespace std;
      7 #define maxn 100020
      8 #define inf 0x3f3f3f3f
      9 
     10 typedef long long ll;
     11 struct node{
     12     int next,to;
     13     void cl(){
     14         next = 0 , to = 0;
     15     }
     16 }e[maxn * 2],e2[maxn * 2];
     17 int head[maxn],head2[maxn],cnt;
     18 int n,m,fa[maxn],val[maxn],vis[maxn];
     19 int idom[maxn],semi[maxn],pnt[maxn],dfn[maxn],id[maxn],dfstime;
     20 ll ans[maxn];
     21 vector <int> ques[maxn];
     22 
     23 inline void clear(){
     24     for (int i = 1 ; i <= cnt ; i++) e[i].cl();
     25     for (int i = 1 ; i <= n ; i++) head[i] = 0;
     26     cnt = 0;
     27     for (int i = 1 ; i <= n ; i++) ques[i].clear();
     28     for (int i = 1 ; i <= n ; i++) ans[i] = 0 , id[i] = pnt[i] = fa[i] = idom[i] = semi[i] = val[i] = vis[i] = 0 , dfn[i] = inf;
     29     dfstime = 0;
     30 }
     31 inline void adde(int x,int y){
     32     e[++cnt].to = y;
     33     e2[cnt].to = x;
     34     e[cnt].next = head[x];
     35     e2[cnt].next = head2[y];
     36     head[x] = cnt;
     37     head2[y] = cnt;
     38 }
     39 inline void adde2(int x,int y){
     40     e[++cnt].to = y;
     41     e[cnt].next = head[x];
     42     head[x] = cnt;    
     43 }
     44 void dfs(int x){
     45     vis[x] = 1, dfn[x] = ++dfstime, id[dfstime] = x;
     46     for (int i = head[x] ; i ; i = e[i].next){
     47         if ( !vis[e[i].to] ) pnt[e[i].to] = x , dfs(e[i].to);
     48     }
     49 }
     50 int getfa(int x){
     51     if ( fa[x] == x ) return x;
     52     int a = getfa(fa[x]);
     53     if ( semi[val[x]] > semi[val[fa[x]]] ) val[x] = val[fa[x]];
     54     return fa[x] = a;
     55 }
     56 inline void merge(int x,int y){
     57     if ( getfa(x) != getfa(y) ) fa[y] = x;
     58 }
     59 void dfs(int x,int fa,ll cur){
     60     cur += (ll)x;
     61     ans[x] = cur;
     62     for (int i = head[x] ; i ; i = e[i].next){
     63         if ( e[i].to == fa ) continue;
     64         dfs(e[i].to,x,cur);
     65     }
     66 }
     67 void calc(){
     68     for (int i = 1 ; i <= cnt ; i++) e[i].cl(), e2[i].cl();
     69     for (int i = 1 ; i <= n ; i++) head[i] = head2[i] = 0;
     70     cnt = 0;
     71     for (int i = 1 ; i <= n ; i++){
     72         if ( idom[i] && idom[i] != i ) adde2(idom[i],i) , adde2(i,idom[i]);
     73     }
     74     dfs(n,0,0);
     75 }
     76 void solve(){
     77     semi[0] = inf;
     78     //val[x]表示到x的祖先中semi最小的点的编号
     79     //semi[x]表示x的半支配点的dfn
     80     for (int i = 1 ; i <= n ; i++) fa[i] = i , semi[i] = inf;
     81     for (int i = dfstime ; i ; i--){
     82         int x = id[i];
     83         for (int j = 0 ; j < ques[x].size() ; j++){
     84             int y = ques[x][j];
     85             getfa(y);
     86             if ( semi[val[y]] < dfn[x] ) idom[y] = val[y];
     87         }
     88         for (int j = head2[x] ; j ; j = e2[j].next){
     89             if ( dfn[x] > dfn[e2[j].to] ) semi[x] = min(semi[x],dfn[e2[j].to]); 
     90             else{
     91                 getfa(e2[j].to);  
     92                 semi[x] = min(semi[x],semi[val[e2[j].to]]);
     93             }
     94         }
     95         if ( pnt[x] ) semi[x] = min(semi[x],dfn[pnt[x]]);
     96         if ( x == n ) semi[x] = 1;
     97         if ( semi[x] < semi[val[x]] ) val[x] = x; 
     98         for (int j = head[x] ; j ; j = e[j].next)
     99             if ( pnt[e[j].to] == x ) merge(x,e[j].to);
    100         ques[id[semi[x]]].push_back(x);
    101     }
    102     for (int i = 1 ; i <= dfstime ; i++){
    103         int x = id[i];
    104         if ( idom[x] ) idom[x] = idom[idom[x]]; //idom[x]最初存的是x到其semi路径上的semi最小值的点
    105         else idom[x] = id[semi[x]];
    106     }
    107 //    for (int i = 1 ; i <= n ; i++) cout<<idom[i]<<" ";
    108 //    cout<<endl;
    109     calc();
    110     for (int i = 1 ; i <= n ; i++){
    111            printf("%lld",ans[i]);
    112         if ( i < n ) printf(" ");
    113     }
    114     printf("
    ");
    115 }
    116 int main(){
    117     freopen("input.txt","r",stdin);
    118     while ( ~scanf("%d %d",&n,&m) ){
    119         clear();
    120         for (int i = 1 ; i <= m ; i++){
    121             int x,y;
    122             scanf("%d %d",&x,&y);
    123             adde(x,y);
    124         }
    125         dfs(n);
    126         solve();
    127     }
    128 }
  • 相关阅读:
    JZOJ 3034. 【NOIP2012模拟10.17】独立集
    JZOJ 3035. 【NOIP2012模拟10.17】铁轨
    JZOJ 1259. 牛棚安排
    数位DP JZOJ 3316. 非回文数字
    JZOJ 3046. 游戏
    JZOJ 3013. 填充棋盘
    debian 安装oracle提供的java8
    java 汉字转拼音 PinYin4j
    debian ssh设置root权限登陆 Permission denied, please try again
    java并发下订单生成策略
  • 原文地址:https://www.cnblogs.com/zqq123/p/5468528.html
Copyright © 2020-2023  润新知