zoukankan      html  css  js  c++  java
  • [POI2014]Rally

    OJ题号:
    BZOJ3832、洛谷3573

    思路:

    建立超级源汇$S$和$T$,DP求出分别以$S$和$T$为源点的最长路$diss$和$dist$。
    对于每条边$i$,设定一个权值$w_i=diss_{i.from}+dist_{i.to}-1$。
    表示原图中包含这条边的从$S$到$T$的最长路。
    然后按照拓扑序删点$x$,用堆维护不包含$x$的最长路长度。
    然而一次性不能把所有边放进去,不然会MLE一个点(因为这个调了一个晚上)。
    应该在换$x$的时候,把老$x$的出边重新加入,并将新$x$的入边删去。
    注意开的数组不能太多,能合并的信息尽量合并,(比如所有边正反边用一个数组存,取值的时候用异或),不然把堆修改以后还是会MLE。

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 #include<ext/pb_ds/priority_queue.hpp>
     6 inline int getint() {
     7     register char ch;
     8     while(!isdigit(ch=getchar()));
     9     register int x=ch^'0';
    10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    11     return x;
    12 }
    13 const int inf=0x7fffffff;
    14 const int V=500002,E=2000000;
    15 struct Edge {
    16     int from,to;
    17 };
    18 Edge e[E];
    19 int w[E];
    20 int s,t;
    21 int n,m;
    22 std::vector<int> eids[V],eidt[V];
    23 int inds[V]={0},indt[V]={0};
    24 inline void add_edge(const int u,const int v,int *ind,std::vector<int> *eid,const int i) {
    25     eid[u].push_back(i);
    26     ind[v]++;
    27 }
    28 int diss[V]={0},dist[V]={0};
    29 std::queue<int> top;
    30 inline void Kahn(const int s,std::vector<int> *eid,int *dis,int *ind,const int op=0) {
    31     std::queue<int> q;
    32     q.push(s);
    33     while(!q.empty()) {
    34         int x=q.front();
    35         q.pop();
    36         if(op) top.push(x);
    37         for(register unsigned i=0;i<eid[x].size();i++) {
    38             int y=e[eid[x][i]].from^e[eid[x][i]].to^x;
    39             dis[y]=std::max(dis[y],dis[x]+1);
    40             if(!--ind[y]) q.push(y);
    41         }
    42     }
    43 }
    44 __gnu_pbds::priority_queue<int> q;
    45 __gnu_pbds::priority_queue<int>::point_iterator p[E];
    46 int v,ans=inf;
    47 int cnt=0;
    48 inline void solve() {
    49     while(!top.empty()) {
    50         int x=top.front();
    51         top.pop();
    52         for(register unsigned i=0;i<eidt[x].size();i++) {
    53             q.erase(p[eidt[x][i]]);
    54         }
    55         if(!q.empty()) {
    56             if((x!=s)&&(x!=t)&&(q.top()<ans)) {
    57                 ans=q.top();
    58                 v=x;
    59             }
    60         }
    61         for(register unsigned i=0;i<eids[x].size();i++) {
    62             p[eids[x][i]]=q.push(w[eids[x][i]]);
    63         }
    64     }
    65 }
    66 int main() {
    67     n=getint(),m=getint();
    68     s=0,t=n+1;
    69     for(register int i=1;i<=n;i++) {
    70         e[cnt].from=s,e[cnt].to=i;
    71         add_edge(s,i,inds,eids,cnt);
    72         add_edge(i,s,indt,eidt,cnt);
    73         cnt++;
    74     }
    75     for(register int i=0;i<m;i++) {
    76         int &u=e[cnt].from=getint(),&v=e[cnt].to=getint();
    77         add_edge(u,v,inds,eids,cnt);
    78         add_edge(v,u,indt,eidt,cnt);
    79         cnt++;
    80     }
    81     for(register int i=1;i<=n;i++) {
    82         e[cnt].from=i,e[cnt].to=t;
    83         add_edge(i,t,inds,eids,cnt);
    84         add_edge(t,i,indt,eidt,cnt);
    85         cnt++;
    86     }
    87     Kahn(s,eids,diss,inds,1);
    88     Kahn(t,eidt,dist,indt);
    89     for(register int i=0;i<cnt;i++) {
    90         w[i]=diss[e[i].from]+dist[e[i].to]-1;
    91     }
    92     solve();
    93     printf("%d %d
    ",v,ans);
    94     return 0;
    95 }
  • 相关阅读:
    论架构在嵌软设计中的重要性
    妙用typeof关键字
    说说动态内存分配
    3个实用shell脚本,建议收藏!
    GNU C语法扩展(7)
    Ubunt_配置_nfs(文件挂载)
    Ubunt_配置_samba(文件共享)
    Ubunt_配置_tftp(文件传输)
    Ubunt_配置_net
    驱动_Platform平台总线
  • 原文地址:https://www.cnblogs.com/skylee03/p/7421211.html
Copyright © 2011-2022 走看看