P3119 [USACO15JAN]草鉴定Grass Cownoisseur
先tarjan缩点 再分层建图 一层为逆向前 另一层为逆向走后 因为逆向只能走一次 所以上去了就下不来了
会不会重复吃草场可以画一下图就能理解辽
给定一个有向图G,有m张优惠券,可以把一条边的边权改成一个固定值k,求节点s到节点t之间最短路的长度和方案数。
方法是建立一个m+1层的多层图,层与层之间的边的权值都为k,然后跑最短路。
由于用了优惠券不一定能达到优化的目的,所以答案为min(t,t+n,t+n+n,...) 方案数也可如此做。
还有一种解法 等我想来理解的时候再来搞叭
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<cmath> #include<stack> #include<algorithm> using namespace std; #define Max(x,y) ((x)>(y)?(x):(y)) #define Min(x,y) ((x)<(y)?(x):(y)) #define ll long long const int N=1e5+5,M=1e5+5,inf=0x3f3f3f3f,P=19650827; int n,m; template <class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } int head[N],tot=0; struct edge{int u,v,nxt;}e[M],e2[M<<2]; void add(int u,int v){ e[++tot]=(edge){u,v,head[u]},head[u]=tot; } int idx=0,Bcnt=0,sz[N<<1],dfn[N],low[N],bl[N]; bool inst[N];stack<int>s; void tarjan(int u){ dfn[u]=low[u]=++idx; s.push(u),inst[u]=1; for(int i=head[u],v;i;i=e[i].nxt){ v=e[i].v; if(!dfn[v]) tarjan(v),low[u]=Min(low[u],low[v]); else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if(dfn[u]==low[u]){ int v;++Bcnt; do{ v=s.top(),s.pop(); bl[v]=Bcnt,inst[v]=0,++sz[Bcnt]; }while(u!=v); } } int head2[N<<1],tot2=0; void add2(int u,int v){ e2[++tot2]=(edge){u,v,head2[u]},head2[u]=tot2; } int dis[N<<1]; bool vis[N<<1];queue<int>q; void spfa(int s){ memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); while(!q.empty()) q.pop(); q.push(s),vis[s]=1; while(!q.empty()){ int u=q.front(); q.pop(),vis[u]=0; for(int i=head2[u],v;i;i=e2[i].nxt){ v=e2[i].v; if(dis[v]<dis[u]+sz[v]){ dis[v]=dis[u]+sz[v]; if(!vis[v]) q.push(v),vis[v]=1; } } } } int main(){ freopen("in.txt","r",stdin); rd(n),rd(m); for(int i=1,u,v;i<=m;++i) rd(u),rd(v),add(u,v); for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); if(sz[bl[1]]==n) {printf("%d",n);return 0;} for(int i=1;i<=Bcnt;++i) sz[i+Bcnt]=sz[i]; for(int i=1;i<=tot;++i) if(bl[e[i].u]!=bl[e[i].v]){ add2(bl[e[i].u],bl[e[i].v]); add2(bl[e[i].v],bl[e[i].u]+Bcnt); add2(bl[e[i].u]+Bcnt,bl[e[i].v]+Bcnt); } spfa(bl[1]); printf("%d",dis[bl[1]+Bcnt]); return 0; }