bzoj-1179(缩点+最短路)
题意:中文题面
解题思路:因为他能重复走且边权都正的,那么肯定一个环的是必须走完的,所以先缩点,在重新建一个图跑最长路
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; const int inf=0x7f7f7f7f; const int maxn=500500; struct node { int num; int dist; node(int _num,int _dist):num(_num),dist(_dist){} friend bool operator<(node a,node b) { return a.dist<b.dist; } }; struct Edge { int next; int to; int w; }edge[maxn],EDGE[maxn]; int low[maxn]; int dfn[maxn]; int scc_cnt; int cnt,indexx,step,CNT; int instack[maxn]; int sccno[maxn]; int visit[maxn]; int head[maxn],HEAD[maxn]; int w[maxn]; int val[maxn]; int dist[maxn]; int flag[maxn]; int x[maxn],y[maxn]; int tx,ty; int n,m; int cot,start; int ans; vector<int>scc[maxn]; void add(int u,int v) { edge[cnt].next=head[u]; edge[cnt].to=v;head[u]=cnt++; } void add2(int u,int v,int w) { EDGE[CNT].next=HEAD[u];EDGE[CNT].to=v; EDGE[CNT].w=w;HEAD[u]=CNT++; } void tarjan(int u) { low[u]=dfn[u]=++step; instack[++indexx]=u; visit[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(visit[v]) { low[u]=min(low[u],dfn[v]); } } if(dfn[u]==low[u]) { scc_cnt++; scc[scc_cnt].clear(); do { scc[scc_cnt].push_back(instack[indexx]); sccno[instack[indexx]]=scc_cnt; visit[instack[indexx]]=0; indexx--; } while(u!=instack[indexx+1]); } return; } void dij(int u) { fill(dist+1,dist+1+scc_cnt,-1); dist[u]=0; priority_queue<node>que; que.push(node(u,dist[u])); while(!que.empty()) { node z=que.top();que.pop(); int now=z.num; for(int i=HEAD[now];i!=-1;i=EDGE[i].next) { int v=EDGE[i].to; if(dist[v]<dist[now]+EDGE[i].w) { dist[v]=dist[now]+EDGE[i].w;//cout<<dist[v]<<endl; que.push(node(v,dist[v])); } } } } void init() { memset(head,-1,sizeof(head));cnt=scc_cnt=indexx=step=0; memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn)); memset(visit,0,sizeof(visit));memset(HEAD,-1,sizeof(HEAD));CNT=0; } int main() { int n,m; init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&tx,&ty); x[i]=tx;y[i]=ty; add(tx,ty); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) scanf("%d",&val[i]); scanf("%d%d",&start,&cot); for(int i=1;i<=cot;i++) scanf("%d",&flag[i]); for(int i=1;i<=scc_cnt;i++) { for(int j=0;j<scc[i].size();j++) { w[i]+=val[scc[i][j]]; if(scc[i][j]==start) start=i; } } add2(0,start,w[start]); for(int i=1;i<=m;i++) { if(sccno[x[i]]==sccno[y[i]]) continue; else { add2(sccno[x[i]],sccno[y[i]],w[sccno[y[i]]]); } } dij(0); ans=0; for(int i=1;i<=cot;i++) { ans=max(ans,dist[sccno[flag[i]]]); } printf("%d\n",ans); }