hdu 3120 dolphin
来源:互联网 发布:网络祼体女主播视频 编辑:程序博客网 时间:2024/05/16 04:57
这个题很不错哦,用到了最短路+二分答案+dfs,出题人太厉害了
首先,100个点,总共的点的标号数目可能达到100,压缩不了,那就只能dfs了,但肯定需要剪枝
我自己想到的剪枝就是,先不管标号的问题,从终点做一次最短路,记录路径,如果源点不可达,则无解,如果这条路径上的点刚好标号都不一样,则输出到源点的最短路径
然后就暴力dfs,如果当前长度加上不考虑标号时当前点到终点的最短路径都大于当前最优解,就返回,这样还是T了
后来想能否快速找到一个可行解作为上限值,但不会找,查了解题报告才知道,可以二分答案,相当于有目的地找多次可行解,然后去验证,很巧妙
这题最让我觉得不可思议的就是每次dfs到一个点的时候都去求一次该点到终点的最短路,用来剪枝,好神奇啊
还有一个值得注意的地方就是,dfs的时候,在进入某个点之前把它标记,然后dfs回来时再撤销标记,否则,在进入某个点后标记,退出这个点时在撤销,可能会由于剪枝而忘记撤销标记的情况
代码:
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<stack>#include<queue>#include<vector>#include<map>#include<ctime>using namespace std;const int MAX=1005;const int inf=1<<26;struct node { int v,w,next;}g[MAX*100];int adj[MAX],e,vis1[MAX],vis2[MAX],kind[MAX],n,m;int dis[MAX],fa[MAX],pre[MAX];int flag[MAX];bool pos[MAX],found;void add(int u,int v,int w){ g[e].v=v; g[e].w=w; g[e].next=adj[u]; adj[u]=e++;}void spfa(int s,int t,int k){ int i,u,v; queue<int>que; for(i=0;i<=n;i++) dis[i]=inf; if(k) memset(pre,-1,sizeof(pre)); dis[s]=0; memset(vis1,0,sizeof(vis1)); vis1[s]=1; que.push(s); while(!que.empty()) { u=que.front(); que.pop(); vis1[u]=0; for(i=adj[u];i!=-1;i=g[i].next) { v=g[i].v; if(vis2[kind[v]]) continue; //if(kind[v]==kind[t]) //continue; //if(kind[v]==kind[s]&&v!=s) //continue; if(dis[v]>dis[u]+g[i].w) { dis[v]=dis[u]+g[i].w; pre[v]=u; if(!vis1[v]) { vis1[v]=1; que.push(v); } } } }} bool check(){ for(int i=0;i<MAX;i++) if(flag[i]>1) return false; return true;}bool dfs(int u,int now,int limit,int t){ if(now>limit) return false; if(u==t) return true; spfa(u,t,0); if(now+dis[t]>limit) return false; int i,v; for(i=adj[u];i!=-1;i=g[i].next) { v=g[i].v; if(vis2[kind[v]]) continue; vis2[kind[v]]=1; if(dfs(v,now+g[i].w,limit,t)) return true; vis2[kind[v]]=0; } return false;}void solve(int s,int t,int sum){ int l=1,r=sum,ans=-1,mid; while(l<=r) { mid=(l+r)>>1; memset(vis2,0,sizeof(vis2)); vis2[kind[s]]=1; if(dfs(s,0,mid,t)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans);}inline int nextInt(){int res = 0; char ch;bool neg = false;while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');if (ch == '-') neg = true;else res = ch - '0';while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - '0';if (neg) res = - res;return res;}int main(){ int i,j,k,T,s,t,sum=0; scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&n,&m,&s,&t); memset(adj,-1,sizeof(adj)); e=0; while(m--) { //scanf("%d%d%d",&i,&j,&k); i=nextInt(); j=nextInt(); k=nextInt(); add(i,j,k); add(j,i,k); sum+=k; } for(i=0;i<n;i++) { //scanf("%d",&kind[i]); kind[i]=nextInt(); } if(s==t) { puts("0"); continue; } memset(vis2,0,sizeof(vis2)); vis2[kind[t]]=1; spfa(t,s,1); memset(flag,0,sizeof(flag)); if(pre[s]==-1) { puts("-1"); continue; } for(i=s;i!=-1;i=pre[i]) { flag[kind[i]]++; } if(check()) { printf("%d\n",dis[s]); continue; } solve(s,t,sum); } return 0;}
- hdu 3120 dolphin
- SRS-DOLPHIN
- Dolphin algorithms - Circulate move
- boonex dolphin安装心得
- dolphin笔试题
- Dolphin Player编译
- 杭电acm Problem3120 Dolphin
- R2D2@Dolphin 成都赛区流水帐
- dolphin:Ubuntu Linux下的WII模拟器
- Dolphin.Integration.Smash.v5.19.1-Lz0
- 开源安卓播放器:Dolphin Player 简单分析
- /Dolphin/Productqa/ 提交问题后404
- 多实例srs:srs-srs-dolphin
- 循环右移——海豚算法(Dolphin)
- 【翻译小手记】This is a dolphin-safe book.
- [圆的离散化 几何] POJ 1688 Dolphin Pool
- [Android]指定浏览器访问指定页面(支持UC、Opera、QQ、Dolphin、Skyfire、Steel、Google)
- 指定浏览器访问指定页面(支持UC、Opera、QQ、Dolphin、Skyfire、Steel、Google)
- VI常用技巧
- Eclipse使用前准备
- 全排列 c++
- Effective C++读书笔记之六
- 全文检索、数据挖掘、推荐引擎系列6---基于KMean的文本自动算法
- hdu 3120 dolphin
- (转)VC调用C#动态库,建立ARX FOR VC工程
- 最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用16
- 打印输入中单词长度的直方图
- 定义Button事件时报错
- accp6.0 《使用javascript增强交互效果》学习笔记ch5 JavaScript和css交互
- C#代码执行过程;值类型和引用类型;深拷贝和浅拷贝
- MyEclipse 6.0.0激活方式
- 最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用17