bzoj 4398 福慧双修 题解
2016-01-08 20:34
417 查看
卡了一晚上啊
首先我们要跑一边整张图的spfa,记录每个点是从哪条边出去的(pre数组)
这里记录的不是前驱边,而是和原点相连的第一个点编号,因为不能走重复边所以才要记录这个,以免刚刚出去又原路返回
那么有一个朴素思路:spfa每一个1点连出去的点
事实上这样是会T的。。。
从这里改进,我们发现上面那种方法走了很多重复的工作,每一次spfa其实是非常类似的
那么我们可以优化一下这个过程:建一张新图跑spfa
这张新图这样建:建立新汇点n+1,设当前边(u,v,w)
1.原点连出的{
pre[v]!=v的话,连1,v,w
否则不连
}
2.连向原点的{
pre[u]!=u 直接用dis[u]+w更新答案
否则连u,n+1,w
}
3.其他的,如果pre[u]==pre[v]从一到v建dis[u]+w的边
否则保留原边
那么新图的最短路就是答案
某个T掉了的
首先我们要跑一边整张图的spfa,记录每个点是从哪条边出去的(pre数组)
这里记录的不是前驱边,而是和原点相连的第一个点编号,因为不能走重复边所以才要记录这个,以免刚刚出去又原路返回
那么有一个朴素思路:spfa每一个1点连出去的点
事实上这样是会T的。。。
从这里改进,我们发现上面那种方法走了很多重复的工作,每一次spfa其实是非常类似的
那么我们可以优化一下这个过程:建一张新图跑spfa
这张新图这样建:建立新汇点n+1,设当前边(u,v,w)
1.原点连出的{
pre[v]!=v的话,连1,v,w
否则不连
}
2.连向原点的{
pre[u]!=u 直接用dis[u]+w更新答案
否则连u,n+1,w
}
3.其他的,如果pre[u]==pre[v]从一到v建dis[u]+w的边
否则保留原边
那么新图的最短路就是答案
某个T掉了的
//Copyright(c)2015 liuchenrui #include<cstdio> #include<ctime> #include<iostream> #include<algorithm> #include<cstring> #define o(e) ((((e)-1)^1)+1) #define inc(a) a++;if(a==100000)a=1; #define inf 1000000000 using namespace std; inline void splay(int &v){ v=0;char c=0;int p=1; while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();} while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();} v*=p; } struct Edge{ int to,next,len; }edge[200010]; int first[100010],size; int dis[40010],dl[100010]; bool exsit[40010]; void addedge(int x,int y,int z){ size++; edge[size].to=y; edge[size].next=first[x]; first[x]=size; edge[size].len=z; } int head,tail; int spfa(int now,int lim){ head=0,tail=1; memset(dis,63,sizeof dis); dis[now]=0,dl[1]=now; while(head!=tail){ inc(head);int v=dl[head];exsit[v]=false; for(int u=first[v];u;u=edge[u].next){ if(edge[u].len+dis[v]<dis[edge[u].to] && u!=lim){ dis[edge[u].to]=edge[u].len+dis[v]; if(!exsit[edge[u].to]){ exsit[edge[u].to]=true; inc(tail);dl[tail]=edge[u].to; } } } } return dis[1]; } int main(){ freopen("xxx.in","r",stdin); freopen("xxx.out","w",stdout); int n,m;splay(n),splay(m); for(int i=1;i<=m;i++){ int s,e,l,r; splay(s),splay(e),splay(l),splay(r); addedge(s,e,l);addedge(e,s,r); } int ans=inf; for(int u=first[1];u;u=edge[u].next){ ans=min(ans,spfa(edge[u].to,o(u))+edge[u].len); } cout<<ans<<endl; }A了的
//Copyright(c)2015 liuchenrui #include<cstdio> #include<ctime> #include<iostream> #include<algorithm> #include<cstring> #define o(e) ((((e)-1)^1)+1) #define inc(a) a++;if(a==100000)a=1; #define inf 1000000000 using namespace std; inline void splay(int &v){ v=0;char c=0;int p=1; while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();} while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();} v*=p; } struct Edge{ int to,next,len,from; }edge[300010],e[300010]; int first[100010],size; int dis[40010],dl[100010]; bool exsit[40010]; int pre[40010]; int f[40010],s; int n,m; void addedge(int x,int y,int z){ size++; edge[size].to=y; edge[size].next=first[x]; first[x]=size; edge[size].len=z; edge[size].from=x; } void add(int x,int y,int z){ s++; e[s].to=y; e[s].next=f[x]; f[x]=s; e[s].len=z; fprintf(stderr,"%d %d %d\n",x,y,z); } int head,tail,ans=inf; void spfa(){ while(head!=tail){ inc(head);int v=dl[head];exsit[v]=false; for(int u=first[v];u;u=edge[u].next){ if(edge[u].len+dis[v]<dis[edge[u].to]){ dis[edge[u].to]=edge[u].len+dis[v]; pre[edge[u].to]=pre[v]; if(!exsit[edge[u].to]){ exsit[edge[u].to]=true; inc(tail);dl[tail]=edge[u].to; } } } } } int Spfa(){ memset(dis,63,sizeof dis); head=0,tail=1;dis[1]=0;dl[1]=1; while(head!=tail){ inc(head);int v=dl[head];exsit[v]=false; for(int u=f[v];u;u=e[u].next){ if(e[u].len+dis[v]<dis[e[u].to]){ dis[e[u].to]=e[u].len+dis[v]; if(!exsit[e[u].to]){ exsit[e[u].to]=true; inc(tail);dl[tail]=e[u].to; } } } } return dis[n+1]; } int main(){ freopen("xxx.in","r",stdin); freopen("xxx.out","w",stdout); splay(n),splay(m); for(int i=1;i<=m;i++){ int s,e,l,r; splay(s),splay(e),splay(l),splay(r); if(s==e&&s==1){ ans=min(ans,l),ans=min(ans,r); } else addedge(s,e,l),addedge(e,s,r); } memset(dis,63,sizeof dis); for(int u=first[1];u;u=edge[u].next){ dl[++tail]=edge[u].to; exsit[edge[u].to]=true; pre[edge[u].to]=edge[u].to; dis[edge[u].to]=edge[u].len; } spfa(); for(int i=1;i<=size;i++){ if(edge[i].to==1){ if(edge[i].from==pre[edge[i].from]){ add(edge[i].from,n+1,edge[i].len); } else{ ans=min(ans,dis[edge[i].from]+edge[i].len); } } else if(edge[i].from==1){ if(pre[edge[i].to]!=edge[i].to){ add(1,edge[i].to,edge[i].len); } } else{ if(pre[edge[i].from]==pre[edge[i].to]){ add(edge[i].from,edge[i].to,edge[i].len); } else{ add(1,edge[i].to,dis[edge[i].from]+edge[i].len); } } } cout<<Spfa()<<endl; }
相关文章推荐
- 车辆管理系统之开始自己的任务(三)
- xcode7真机调试identifier not avaliable错误
- 11 是否存在子树 & 二叉树镜像
- 水池数目 OJ 27
- java中读取配置文件的方法
- 【杭电oj】2719 - The Seven Percent Solution (特殊字符输出)(水)
- 用户空间的open()是怎么调用到file_operations中提供的open函数的
- NSURLSession post -- NSURLSessionDataTask
- Java程序猿的JavaScript学习笔记(3——this/call/apply)
- 18. 4Sum
- 3. Twitter的客户端框架——Bootstrap
- myeclipse与数据库进行连接(无需写代码进行验证)
- 傅里叶变换的通俗解释—转载
- wyx
- 层次分析法(AHP)的Matlab实现
- 嵌入式
- 【慕课笔记】第二章 变量和常量 第2节 认识JAVA标识符
- Security 可视化
- struts2配置内置校验器
- 建立nfs共享