【传送门:BZOJ1179】
简要题意:
有n个城市,其中有一座中心城市,m条单向的道路连接城市,每一个城市里都可以获得钱,而有部分城市有酒吧,不限步数,每条道路可以重复走,但是一个城市里的钱不能重复获取,要求从中心城市出发,到任意一个有酒吧的城市所能获得的最大钱数
此处更正一下BZOJ的样例输入数据:
6 7
1 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1
5
1 4
4 3 5 6
题解:
因为有可能出现环,而且样例输入数据就出现了(很温馨的数据),所以我们先用强联通来缩点,然后将每个强联通之间通过原来的边来建新的边,直接跑最短路得出答案(因为我是蒟蒻,不懂拓扑,只好这样做了QAQ)
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; struct node { int x,y,next; }a[510000];int len,last[510000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int d[510000]; bool v[510000]; int sta[510000],tp; int belong[510000],cnt; int low[510000],dfn[510000],id; bool b[510000]; void dfs(int x) { dfn[x]=low[x]=++id; sta[++tp]=x;v[x]=true; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(dfn[y]==0) { dfs(y); low[x]=min(low[x],low[y]); } else { if(v[y]==true) low[x]=min(low[x],low[y]); } } if(low[x]==dfn[x]) { int i;cnt++; do { i=sta[tp--]; belong[i]=cnt; v[i]=false; }while(i!=x); } } struct SPFA { int x,y,d,next; }e[510000];int elen,elast[510000]; int list[510000]; int head,tail; void eins(int x,int y,int d) { elen++; e[elen].x=x;e[elen].y=y;e[elen].d=d; e[elen].next=elast[x];elast[x]=elen; } int dep[510000]; bool bo[510000]; int main() { int n,m; scanf("%d%d",&n,&m); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); ins(x,y); } memset(sta,0,sizeof(sta)); memset(v,false,sizeof(v)); memset(belong,0,sizeof(belong)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); id=cnt=tp=0; for(int i=1;i<=n;i++) { if(dfn[i]==0) dfs(i); } memset(d,0,sizeof(d)); for(int i=1;i<=n;i++) { int c; scanf("%d",&c); d[belong[i]]+=c; } int st,p; scanf("%d%d",&st,&p); st=belong[st]; memset(b,false,sizeof(b)); for(int i=1;i<=p;i++) { int x; scanf("%d",&x); b[belong[x]]=true; } memset(elast,0,sizeof(elast));elen=0; for(int i=1;i<=len;i++) { int x=a[i].x,y=a[i].y; if(belong[x]!=belong[y]) { eins(belong[x],belong[y],d[belong[y]]); } } eins(0,st,d[st]); head=1;tail=2;list[1]=0; dep[0]=0; memset(bo,false,sizeof(bo));bo[0]=true; int ans=0; while(head!=tail) { int x=list[head]; for(int k=elast[x];k;k=e[k].next) { int y=e[k].y; if(dep[y]<dep[x]+e[k].d) { dep[y]=dep[x]+e[k].d; if(b[y]==true) ans=max(ans,dep[y]); if(bo[y]==false) { bo[y]=true; list[tail++]=y; } } } bo[x]=false;head++; } printf("%d ",ans); return 0; }