Gym

来源:互联网 发布:网络玄幻小说合集下载 编辑:程序博客网 时间:2024/06/05 04:29

这题和sgu298是一个题,但是在sgu上这个题是1.5s,在gym上是0.5s,就很坑。。。

题意可以看一下点击打开链接

查分约束,一般的做法是用spfa算法,但这题会TLE...各种乱改了好长时间,在vj上看了别人一个代码才明白

可以先用tarjan算法求强连通分量,如果一个点和他相邻的点在同一个强连通分量里,则无解

然后缩点,在用拓扑排序替代spfa求解

这样的复杂度只有O(e)

#include<cstdio>#include<algorithm>#include<cstring>#include<queue>using namespace std;const int maxn=10005;const int maxm=300005;int n,m;int headz[maxn],headf[maxn];int tot,ord,scc,top,idx;int disz[maxn],disf[maxn];int vis[maxn],inq[maxn];int instack[maxn];int DFN[maxn];int low[maxn];int st[maxn];int block[maxn];int head[maxn];int que[maxn],que2[maxn];int indeg[maxn],outdeg[maxn];struct node{int v,next,dis;}edgez[maxm],edgef[maxm],edge[maxm];void addedge(int u,int v,int d){edgez[tot].v=v;edgez[tot].dis=d;edgez[tot].next=headz[u];headz[u]=tot;edgef[tot].v=u;edgef[tot].dis=d;edgef[tot].next=headf[v];headf[v]=tot++;}void add(int u,int v,int d){edge[idx].v=v;edge[idx].dis=d;edge[idx].next=head[u];head[u]=idx++;}void init(){memset(headz,-1,sizeof(headz));memset(headf,-1,sizeof(headf));memset(head,-1,sizeof(head));tot=0;ord=0;scc=0;top=0;idx=0;}void tarjan(int u){DFN[u]=low[u]=++ord;instack[st[++top]=u]=1;for(int i=head[u];~i;i=edge[i].next){int v=edge[i].v;if(!DFN[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(instack[v])low[u]=min(low[u],DFN[v]);}int v;if(DFN[u]==low[u]){scc++;do{instack[v=st[top--]]=0;block[v]=scc; }while(v!=u);}}int check(){int u,v,d;scanf("%d%d",&n,&m);for(int i=0;i<m;i++){scanf("%d%d%d",&u,&v,&d);add(u,v,d);}for(int i=1;i<=n;i++){if(!DFN[i])tarjan(i);}for(int i=1;i<=n;i++){for(int j=head[i];j!=-1;j=edge[j].next){int v=edge[j].v;if(block[i]==block[v]&&edge[j].dis)return 0;else if(block[i]!=block[v]){++indeg[block[v]];++outdeg[block[i]];addedge(block[i],block[v],edge[j].dis);}}}return 1;}int solve(){int front=0,rear=0,front2=0,rear2=0;for(int i=1;i<=scc;i++){disz[i]=10000;disf[i]=-10000;if(!indeg[i])que[++rear]=i;if(!outdeg[i])que2[++rear2]=i;}while(front!=rear){int t=que[++front];for(int i=headz[t];i!=-1;i=edgez[i].next){int v=edgez[i].v;--indeg[v];disz[v]=min(disz[v],disz[t]-edgez[i].dis);if(!indeg[v])que[++rear]=v;}}while(front2!=rear2){int t=que2[++front2];for(int i=headf[t];i!=-1;i=edgef[i].next){int v=edgef[i].v;--outdeg[v];disf[v]=max(disf[v],disf[t]+edgef[i].dis);if(!outdeg[v])que2[++rear2]=v;}}for(int i=1;i<=scc;i++){if(disz[i]<=disf[i])return 0;}return 1;}void getans(){disz[block[n]]=disf[block[n]];for(int i=1;i<=scc;i++){for(int j=headz[que[i]];j!=-1;j=edgez[j].next){disz[edgez[j].v]=min(disz[edgez[j].v],disz[que[i]]-edgez[j].dis);}}for(int i=1;i<n;i++)printf("%d ",disz[block[i]]);printf("%d\n",disz[block[n]]);}int main(){init();if(!check())printf("-1\n");else if(!solve())printf("-1\n");else getans();return 0; } 

0 0
原创粉丝点击