zoukankan      html  css  js  c++  java
  • [补档][Usaco2015 Jan]Grass Cownoisseur

    [Usaco2015 Jan]Grass Cownoisseur

    题目

    给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?
    (一个点在路径中无论出现多少正整数次对答案的贡献均为1)

    INPUT

    The first line of input contains N and M, giving the number of fields and the number of one-way paths (1 <= N, M <= 100,000). The following M lines each describe a one-way cow path. Each line contains two distinct field numbers X and Y, corresponding to a cow path from X to Y. The same cow path will never appear more than once.
    N个点,M条有向边,无重边

    OUTPUT

    A single line indicating the maximum number of distinct fields Bessie
    can visit along a route starting and ending at field 1, given that she can
    follow at most one path along this route in the wrong direction.

    SAMPLE

    INPUT

    7 10
    1 2
    3 1
    2 5
    2 4
    3 7
    3 5
    3 6
    6 5
    7 2
    4 7

    OUTPUT

    6

    解题报告

    这道题考试的时候,一看就知道是tarjan,然后就真的傻傻的打了个tarjan+dfs,就A了一个点= =
    正解:
    tarjan缩点,因为可以逆转一条边,而同一强连通分量里的边逆转是没啥用的,所以我们可以枚举缩点后的边。
    首先,跑2遍SPFA,一遍缩点后的正边,一遍反边,处理出正反两个最大的经过权值(每点权值为缩点后强连通分量的点数)。
    剩下的就很简单了,思考当一条有向边反过来时,它反边的起点走的是正向的最大权值,而终点则走的是反向的最大权值,那么我们枚举每一条边,两权相加求max即为答案。
    注意:特判,两边SPFA若有一遍没有联通这条边对应的强连通分量,这个点就不能跑。
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<queue>
      5 using namespace std;
      6 inline int read(){
      7     int sum(0);
      8     char ch(getchar());
      9     while(ch<'0'||ch>'9')
     10         ch=getchar();
     11     while(ch>='0'&&ch<='9'){
     12         sum=sum*10+ch-'0';
     13         ch=getchar();
     14     }
     15     return sum;
     16 }
     17 struct edge{
     18     int s,e,n;
     19 }k[100001],a[100001],b[100001];
     20 int pre[100001],tot;
     21 inline void insert(int s,int e){
     22     k[++tot].s=s;
     23     k[tot].e=e;
     24     k[tot].n=pre[s];
     25     pre[s]=tot;
     26 }
     27 int low[100001],dfn[100001],stack[100001],bl[100001],size[100001];
     28 int head,cnt,qlt;
     29 bool vis[100001];
     30 inline int my_min(int a,int b){
     31     return a<b?a:b;
     32 }
     33 inline int my_max(int a,int b){
     34     return a>b?a:b;
     35 }
     36 inline void tarjan(int u){
     37     low[u]=dfn[u]=++cnt;
     38     vis[u]=1;
     39     stack[++head]=u;
     40     for(int i=pre[u];i!=-1;i=k[i].n){
     41         int e(k[i].e);
     42         if(!dfn[e]){
     43             tarjan(e);
     44             low[u]=my_min(low[u],low[e]);
     45         }
     46         else
     47             if(vis[e])
     48                 low[u]=my_min(low[u],dfn[e]);
     49     }
     50     if(low[u]==dfn[u]){
     51         int tmp;
     52         qlt++;
     53         while(1){
     54             tmp=stack[head--];
     55             bl[tmp]=qlt;
     56             vis[tmp]=0;
     57             if(tmp==u)
     58                 break;
     59         }
     60     }
     61 }
     62 int adj[100001],num;
     63 inline void add(int s,int e){
     64     a[++num].s=s;
     65     a[num].e=e;
     66     a[num].n=adj[s];
     67     adj[s]=num;
     68 }
     69 queue<int>q;
     70 int fz[100001];
     71 inline void spfa1(int x){
     72     memset(vis,0,sizeof(vis));
     73     memset(fz,0,sizeof(fz));
     74     q.push(x);
     75     fz[x]=size[x];
     76     vis[x]=1;
     77     while(!q.empty()){
     78         int k(q.front());
     79         q.pop();
     80         for(int i=adj[k];i!=-1;i=a[i].n){
     81             int e(a[i].e);
     82             if(fz[e]<fz[k]+size[e]){
     83                 fz[e]=fz[k]+size[e];
     84                 if(!vis[e]){
     85                     q.push(e);
     86                     vis[e]=1;
     87                 }
     88             }
     89         }
     90         vis[k]=0;
     91     }
     92 }
     93 int hhh,nxt[100001];
     94 inline void init(int s,int e){
     95     b[++hhh].s=s;
     96     b[hhh].e=e;
     97     b[hhh].n=nxt[s];
     98     nxt[s]=hhh;
     99 }
    100 int ff[100001];
    101 inline void spfa2(int x){
    102     memset(vis,0,sizeof(vis));
    103     memset(ff,0,sizeof(ff));
    104     q.push(x);
    105     ff[x]=size[x];
    106     vis[x]=1;
    107     while(!q.empty()){
    108         int k(q.front());
    109         q.pop();
    110         for(int i=nxt[k];i!=-1;i=b[i].n){
    111             int e(b[i].e);
    112             if(ff[e]<ff[k]+size[e]){
    113                 ff[e]=ff[k]+size[e];
    114                 if(!vis[e]){
    115                     q.push(e);
    116                     vis[e]=1;
    117                 }
    118             }
    119         }
    120         vis[k]=0;
    121     }
    122 }
    123 inline int find(int x){
    124     int s(a[x].e),e(a[x].s);
    125     if(!fz[s]||!ff[e])
    126         return 0;
    127     return fz[s]+ff[e]-size[bl[1]];
    128 }
    129 int n,m;
    130 int main(){
    131     memset(pre,-1,sizeof(pre));
    132     memset(adj,-1,sizeof(adj));
    133     memset(nxt,-1,sizeof(nxt));
    134     n=read(),m=read();
    135     for(int i=1;i<=m;i++){
    136         int x(read()),y(read());
    137         insert(x,y);
    138     }
    139     for(int i=1;i<=n;i++)
    140         if(!dfn[i])
    141             tarjan(i);
    142     for(int i=1;i<=n;i++)
    143         size[bl[i]]++;
    144     for(int i=1;i<=tot;i++){
    145         int s(k[i].s),e(k[i].e);
    146         if(bl[s]!=bl[e])
    147             add(bl[s],bl[e]),init(bl[e],bl[s]);
    148     }
    149     spfa1(bl[1]);
    150     spfa2(bl[1]);
    151     int ans(0);
    152     for(int i=1;i<=num;i++)
    153         ans=my_max(ans,find(i));
    154     printf("%d
    ",ans);
    155 }
    View Code
    ps:调了我两个小时,最后发现重新建边的时候我用的原来点的编号,没有用缩完点后的编号,然后就听取蛙声一片了= =
  • 相关阅读:
    Spring包的依赖关系以及提供下载
    正则
    Spring征服数据库
    Java之多线程同步基础
    Java之多线程优先级基础
    ColorMatrixFilter色彩矩阵滤镜
    AS3.0 位图翻转、旋转
    AS3.0 自定义右键菜单类
    精确选择识别png图片有像素的区域
    AS3动画效果常用公式
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7275990.html
Copyright © 2011-2022 走看看