zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Jmeter
    http请求的全过程
    前端知识
    jmeter连接MySQL数据库、sqlserver数据库
    jmeter 生成随机字符串、获取当前时间
    jmeter跨线程组传参
    fiddler抓不到iis网站包的问题
    jmeter登录数据库-- 通过windows身份验证方法(DNS)
    ant安装(Windows系统)
    tomcat安装(Windows系统)
  • 原文地址:https://www.cnblogs.com/zqq123/p/5468528.html
Copyright © 2011-2022 走看看