poj1734 - Sightseeing trip

来源:互联网 发布:重生之网络大亨txt下载 编辑:程序博客网 时间:2024/06/06 01:49

                                  想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
                                  转载请注明出处:http://blog.csdn.net/wangjian8006

题目大意:给出你一个无向图,要你求一个最小环,最小环的最少有3个节点,如果有环则顺序输出节点上的点,如果没有环,输出NO solution.
数据比较弱,测试数据是有重边的,但是我没考虑都过了.

解题思路:刚看到这题有点凌乱,没思路,后来想到深搜去找一个最小环居然过了
前面我的想法是:一个最小环,对于环上的两点,环的路径是等于两点的最短路径与次短路径只和的,不过接下来就断了。然后直接暴力深搜写了
在网上找了资料,发现是用floyd变形去做,跟着模板又写了一次,看懂了感觉好神奇

/*DFSMemory 212KTime  125MS*/#include <iostream>#include <vector>using namespace std;#define MAXV 110#define INF INT_MAXint map[MAXV][MAXV];bool mark[MAXV];int ans[MAXV],ans_sum;int n,m,key,head;int temp[MAXV];void dfs(int x,int sum,int ns,int parent){//当前节点,从head开始找到x的路径长度,找到了多少个节点,x的父亲节点int i;if(x==head && mark[head]){if(key>sum){key=sum;ans_sum=ns;for(i=0;i<ans_sum;i++)ans[i]=temp[i];}return ;}temp[ns]=x;for(i=1;i<=n;i++){if(!map[x][i]) continue;if(i!=head && mark[i]) continue;//如果t被找过,而且t不是head的环,那么不用找if(i==parent) continue;//不能往回走mark[i]=1;if(sum+map[x][i]<key) dfs(i,sum+map[x][i],ns+1,x);mark[i]=0;}}int main(){int i,a,b,c;while(~scanf("%d%d",&n,&m)){memset(map,0,sizeof(map));for(i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);map[a][b]=map[b][a]=c;}key=INF;for(i=1;i<=n;i++){//对于每个节点,找出这节点的最小环memset(mark,0,sizeof(mark));head=i;dfs(i,0,0,0);}if(key==INF){printf("No solution.\n");}else{for(i=0;i<ans_sum;i++) printf("%d ",ans[i]);printf("\n");}}return 0;}


=========================================================================================================

/*floydMemory 284KTime   16MS*/#include <iostream>using namespace std; #define MAXV 101#define INF 0x7ffffff#define min(a,b) a<b?a:b int map[MAXV][MAXV],dist[MAXV][MAXV],pre[MAXV][MAXV],ans[MAXV],n;intkey,ans_sum;void floyd(){int i,j,k;key=INF;for(k=1;k<=n;k++){//最短路径外一点将最短路首尾链接,那么就得到一个最小环 for(i=1;i<k;i++){ for(j=i+1;j<k;j++){ //求最小环不能用两点间最短路松弛,因为(i,k)之间的最短路,(k,j)之间的最短路可能有重合的部分 //所以map[][]其实是不更新的,这里和单纯的floyd最短路不一样 //dist[i][j]保存的是 i 到 j 的最短路权值和 int tmp=dist[i][j]+map[i][k]+map[k][j];//这里 k 分别和 i 还有 j 在mat中直接相连 if(tmp<key){key=tmp;ans_sum=0;int p=j;while(p!=i){//回溯 ans[ans_sum++]=p;p=pre[i][p];//pre[i][j]表示 i 到 j 最短路径上 j 前面的一个点}ans[ans_sum++]=i;ans[ans_sum++]=k;}}}for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(dist[i][j]>dist[i][k]+dist[k][j]){dist[i][j]=dist[i][k]+dist[k][j];//dist[][]保存两点间最短距离pre[i][j]=pre[k][j];}}}}}int main(){     int i,j,m,a,b,c;    while(~scanf("%d%d",&n,&m)){         for(i=1;i<=n;i++){             for(j=1;j<=n;j++){                 map[i][j]=dist[i][j]=INF;                 pre[i][j]=i;             }         }         while(m--){            scanf("%d%d%d",&a,&b,&c);            map[a][b]=map[b][a]=dist[a][b]=dist[b][a]=min(map[a][b],c);         }floyd();        if(key==INF)puts("No solution.\n");         else{            printf("%d",ans[0]);             for(i=1;i<ans_sum;i++)                 printf(" %d",ans[i]);             printf("\n");        }    }    return 0; }