【USACO 2015 Jan Gold】强连通分量+最长路
来源:互联网 发布:知乎 性观念 编辑:程序博客网 时间:2024/05/01 10:59
NKOJ 3213牧草鉴赏家
问题描述
约翰有n块草场,编号1到n,这些草场由若干条单行道相连。奶牛贝西是美味牧草的鉴赏家,她想到达尽可能多的草场去品尝牧草。
贝西总是从1号草场出发,最后回到1号草场。她想经过尽可能多的草场,贝西在通一个草场只吃一次草,所以一个草场可以经过多次。因为草场是单行道连接,这给贝西的品鉴工作带来了很大的不便,贝西想偷偷逆向行走一次,但最多只能有一次逆行。问,贝西最多能吃到多少个草场的牧草。
输入格式
第一行,两个整数N和M(1<=N,M<=100000)
接下来M行,表示有M条单向道路,每条道路有连个整数X和Y表示,从X出发到达Y。
输出格式
一个整数,表示所求答案
首先可以想到,处于同一个强连通分量的点,如果能够从1号点走到强连通分量中,那么就能够全部吃完。因此我们可以用Tarjan算法缩点。
缩完点之后,就变成了一个有向无环图。然而我们最后还是要回到1号点,所以就有两种情况:
1.只吃完与起点处在同一个强连通分量的所有草;
2.通过逆行回到起点。
主要讨论情况2。此时逆行的边 < a, b > 显然满足从起点能够到达a,且从b能够到达起点。那么为了解决“从b能够到达起点”,对原图建一个反图。分别对原图与反图跑一次最短路算法后,枚举逆边即可。
#include<stdio.h>#include<stack>#include<queue>#define Min(x,y) ((x<y)?(x):(y))#define Max(x,y) ((x>y)?(x):(y))#define MAXN 100005#define MAXM 200005using namespace std;int N,M,T,Size[MAXN],Ans;inline int _R(){ char s=getchar();int v=0,sign=0; while((s!='-')&&(s>57||s<48))s=getchar(); if(s=='-')sign=1,s=getchar(); for(;s>47&&s<58;s=getchar())v=v*10+s-48; if(sign)v=-v; return v;}int tot,en[MAXM],nex[MAXM],las[MAXN];void ADD_scc(int x,int y){ en[++tot]=y; nex[tot]=las[x]; las[x]=tot;}stack<int>S;int VT,scc,be[MAXN],dfn[MAXN],low[MAXN];bool mark[MAXN];void Tarjan(int x){ dfn[x]=low[x]=++VT; mark[x]=true; S.push(x); int i,y; for(i=las[x];i;i=nex[i]) { y=en[i]; if(!dfn[y]) { Tarjan(y); low[x]=Min(low[x],low[y]); } else if(mark[y])low[x]=Min(low[x],dfn[y]); } if(dfn[x]!=low[x])return; scc++; do { y=S.top();S.pop();mark[y]=false; be[y]=scc; }while(y!=x);}int Tot,En[MAXM],Las[MAXN],Nex[MAXM],Len[MAXM],St[MAXM];bool inv[MAXM];void ADD(int x,int y,int z,int w){ En[++Tot]=y; Nex[Tot]=Las[x]; Las[x]=Tot; Len[Tot]=z; St[Tot]=x; inv[Tot]=w;}struct node{int p,al;};bool in[MAXN][2];int Dis[MAXN][2];void SPFA1(int s){ queue<int>Q; int i,y,x,z; for(i=1;i<=scc;i++)Dis[i][0]=-1e9; Dis[s][0]=0; Q.push(s); while(Q.size()) { x=Q.front();Q.pop(); in[x][0]=false; for(i=Las[x];i;i=Nex[i]) { y=En[i]; if(inv[i])continue; if(Dis[y][0]<Dis[x][0]+Len[i]) { Dis[y][0]=Dis[x][0]+Len[i]; if(!in[y][0]){in[y][0]=true;Q.push(y);} } } }}//原图void SPFA2(int s){ queue<int>Q; int i,y,x,z; for(i=1;i<=scc;i++)Dis[i][1]=-1e9; Dis[s][1]=0; Q.push(s); while(Q.size()) { x=Q.front();Q.pop(); in[x][1]=false; for(i=Las[x];i;i=Nex[i]) { y=En[i]; if(!inv[i])continue; if(Dis[y][1]<Dis[x][1]+Len[i]) { Dis[y][1]=Dis[x][1]+Len[i]; if(!in[y][1]){in[y][1]=true;Q.push(y);} } } }}//反图int main(){ int i,j,x,y; scanf("%d%d",&N,&M); for(i=1;i<=M;i++) { scanf("%d%d",&x,&y); ADD_scc(x,y); } for(i=1;i<=N;i++)if(!dfn[i])Tarjan(i); for(i=1;i<=N;i++)Size[be[i]]++; for(x=1;x<=N;x++) { for(i=las[x];i;i=nex[i]) { y=en[i]; if(be[x]==be[y])continue; ADD(be[x],be[y],Size[be[y]],0); ADD(be[y],be[x],Size[be[x]],1); } } T=be[1]; SPFA1(T); SPFA2(T); for(i=1;i<=Tot;i++) { if(!inv[i])continue; x=St[i];y=En[i]; if(Dis[x][0]!=-1e9&&Dis[y][1]!=-1e9)Ans=Max(Ans,(Dis[x][0]+Dis[y][1]));//枚举逆边,如果Dis为-1e9,说明到不了 } printf("%d",Ans+Size[T]);//与起点在同一强连通分量的草也能吃到}
阅读全文
0 0
- 【USACO 2015 Jan Gold】强连通分量+最长路
- 【强连通分量】奶牛偶像 usaco 2003
- POJ3592 Instantaneous Transference【强连通分量】【最长路】
- Instantaneous Transference poj3592(【强连通分量】【最长路】)
- P3213【USACO 2015 Jan Gold】牧草鉴赏家
- UVA 11324 强连通分量 最长链
- 【连通图|强连通分量+最长路】POJ-3592 Instantaneous Transference
- USACO Network of Schools(学校网络) ---强连通分量
- usaco 5.3 Network of Schools(强连通分量+构造强连通最少边)
- UVA11324_The Largest Clique_tarjan求强连通分量+DP求最长路
- 训练赛 Grouping(强连通分量缩点 + DAG求最长路)
- poj 3592 强连通分量+最长路(spfa或者dp)(Instantaneous Transference)
- POJ - 3160 Father Christmas flymouse(最长路+强连通分量)
- POJ 3160 Father Christmas flymouse(强连通分量+spfa最长路)
- UVa 11324 最大团(强连通分量+dp最长路)
- poj 3592 Instantaneous Transference (借助强连通分量求缩点在建图spfa求最长路)
- 强连通分量,DAG上的最长路,记忆化搜索(最大团,UVA 11324)
- POJ 3592 Instantaneous Transference (强连通分量 缩点 spfa最长路)
- 程序猿与艺术的碰撞
- Sending signal. PID: 8561 SIG: 9
- java中NIO和IO的区别
- LintCode Longest Common Subsequence(最长公共子序列长度,动态规划入门题)
- 练习三(第二周)
- 【USACO 2015 Jan Gold】强连通分量+最长路
- Django缓存系统
- HDFS启动过程了解
- 欢迎使用CSDN-markdown编辑器
- UVA 11825 状态压缩DP
- MacOS 开发
- 从零开始的"E"世界(J2SE)
- 像加载DLL一样加载EXE
- Connections in Galaxy War