BZOJ 1880 [Sdoi2009]Elaxia的路线

来源:互联网 发布:java 防止xss攻击 编辑:程序博客网 时间:2024/06/05 09:57

大家都说这是一道大水题。。。想打dyx

应该了解到拓扑排序的功能,类比于食物链那道题,拓扑排序可以dp求出最长链。而在这道题只需求出可以重复的部分搞一个拓扑排序即可。

而怎样求重复的部分呢?有一个思想很好:将一条线路拆分成起点到此的距离和终点到此的距离,跑两遍单源最短路,然后类似地枚举求出一些可以重复的路径,Topo一下就好了

(尝试新代码风格2333,bz会卡空间,实测将边的数量开小一半就可以过了)

#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<queue>#include<algorithm>using namespace std;const int maxn=1501;struct edge{    int from,to,next,val;}oe[maxn*maxn>>1],nowe[maxn*maxn>>1];int n,ocnt,nowcnt,ans,m,S1,S2,T1,T2;int ohead[maxn],nowhead[maxn],f[maxn],degree[maxn];int dists1[maxn],dists2[maxn],distt1[maxn],distt2[maxn];bool vst[maxn];void insert(int &cnt,int head[],edge e[],int from,int to,int val){    e[++cnt].from=from;e[cnt].to=to;e[cnt].val=val;e[cnt].next=head[from];head[from]=cnt;}void spfa(int S,int head[],edge e[],int dist[]){    queue<int>q;    memset(dist+1,0x3f,sizeof(int)*n);    memset(vst+1,0,sizeof(bool)*n);    q.push(S);    vst[S]=true;dist[S]=0;    while(!q.empty())    {        int u=q.front();        q.pop();        vst[u]=false;        for(int i=head[u];i;i=e[i].next)        {            int v=e[i].to;            if(dist[u]+e[i].val<dist[v])            {                dist[v]=dist[u]+e[i].val;                if(!vst[v])vst[v]=true,q.push(v);            }        }    }}void Topological_sort(int head[],edge e[]){    memset(f+1,0,sizeof(int)*n);    queue<int>q;    for(int i=1;i<=n;i++)        if(!degree[i])q.push(i);    while(!q.empty())    {        int u=q.front();        q.pop();        for(int i=head[u];i;i=e[i].next)        {            int v=e[i].to;            f[v]=max(f[v],f[u]+e[i].val);            ans=max(ans,f[v]);            degree[v]--;            if(!degree[v])q.push(v);        }    }}int main(){    scanf("%d%d",&n,&m);    scanf("%d%d%d%d",&S1,&T1,&S2,&T2);    for(int i=1,u,v,val;i<=m;i++)    {        scanf("%d%d%d",&u,&v,&val);        insert(ocnt,ohead,oe,u,v,val);        insert(ocnt,ohead,oe,v,u,val);    }    spfa(S1,ohead,oe,dists1);    spfa(T1,ohead,oe,distt1);    spfa(S2,ohead,oe,dists2);    spfa(T2,ohead,oe,distt2);    for(int i=1;i<=ocnt;i++)        if(dists1[oe[i].from]+oe[i].val+distt1[oe[i].to]==dists1[T1])            if(dists2[oe[i].from]+oe[i].val+distt2[oe[i].to]==dists2[T2])                insert(nowcnt,nowhead,nowe,oe[i].from,oe[i].to,oe[i].val),degree[oe[i].to]++;    Topological_sort(nowhead,nowe);    memset(nowhead+1,0,sizeof(int)*n);    memset(degree+1,0,sizeof(int)*n);    nowcnt=0;    for(int i=1;i<=ocnt;i++)        if(dists1[oe[i].from]+oe[i].val+distt1[oe[i].to]==dists1[T1])            if(distt2[oe[i].from]+oe[i].val+dists2[oe[i].to]==distt2[S2])            insert(nowcnt,nowhead,nowe,oe[i].from,oe[i].to,oe[i].val),degree[oe[i].to]++;    Topological_sort(nowhead,nowe);    cout<<ans;    return 0;}