题意:

  给一个带权无向图,求其至少有3个点组成的环的最小权之和。

思路:

  (1)DFS可以做,实现了确实可以,只是TLE了。量少的时候应该还是可以水一下的。主要思路就是,深搜过程如果当前点搜到一个点访问过了,而其不是当前点的父亲,则肯定有环,可以更新答案。深搜过程要记录路径和,父亲,是否访问过等等信息,因为图可能有多个连通分量。

 #include <bits/stdc++.h>
#define INF 0x7f7f7f7f
#define pii pair<int,int>
#define LL unsigned long long
using namespace std;
const int N=;
struct node
{
int from, to, cost;
node(){};
node(int from,int to,int cost):from(from),to(to),cost(cost){};
}edge[N*N];
int edge_cnt;
vector<int> vect[N]; void add_node(int from,int to,int cost)
{
edge[edge_cnt]=node(from, to, cost);
vect[from].push_back(edge_cnt++);
} int sum[N], vis[N], inq[N], pre[N], ans; void DFS(int x)
{
vis[x]=;
inq[x]=;
for(int i=; i<vect[x].size(); i++)
{
node e=edge[vect[x][i]];
if( inq[e.to] && pre[x]!=e.to )
{
ans=min(ans, sum[x]+e.cost-sum[e.to]);
}
if( !inq[e.to] )
{
pre[e.to]=x;
sum[e.to]=sum[x]+e.cost;
DFS(e.to);
sum[e.to]=;
pre[e.to]=;
}
}
inq[x]=;
} int cal(int n)
{
ans=INF;
memset(vis,,sizeof(vis));
memset(inq,,sizeof(inq));
memset(pre,,sizeof(pre));
memset(sum,,sizeof(sum));
for(int i=; i<=n; i++)
{
if(!vis[i])
DFS(i);
}
return ans==INF? : ans;
} int main()
{
freopen("input.txt", "r", stdin);
int t, a, b, c, n, m;
while(~scanf("%d %d", &n, &m))
{
edge_cnt=;
for(int i=; i<=n; i++) vect[i].clear(); for(int i=; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
add_node(a, b, c);
add_node(b, a, c);
} int ans=cal(n);
if(ans) printf("%d\n", ans);
else printf("It's impossible.\n");
}
return ;
}

TLE代码

  (2)dijkstra。枚举删除某一条边,求该边两点间的最短距离。要注意的是,重边只留1条权最小的,其他删掉,这样就能保证至少出现3个点。

  608ms

 #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <deque>
#define INF 0x7f7f7f7f
#define pii pair<int,int>
#define LL unsigned long long
using namespace std;
const int N=;
struct node
{
int from, to, cost, tag;
node(){};
node(int from,int to,int cost):from(from),to(to),cost(cost),tag(){};
}edge[N*N];
int edge_cnt;
vector<int> vect[N];
int g[N][N];
void add_node(int from,int to,int cost)
{
edge[edge_cnt]=node(from, to, cost);
vect[from].push_back(edge_cnt++);
} int vis[N], cost[N];
int dijkstra(int s,int e)
{
memset(cost, 0x7f, sizeof(cost));
memset(vis, , sizeof(vis));
cost[s]=;
priority_queue<pii,vector<pii>,greater<pii> > que;
que.push(make_pair(, s)); while(!que.empty())
{
int x=que.top().second;
que.pop();
if(vis[x]) continue;
vis[x]=;
for(int i=; i<vect[x].size(); i++)
{
node e=edge[vect[x][i]];
if( e.tag && cost[e.to]>cost[x]+e.cost )
{
cost[e.to]=cost[x]+e.cost;
que.push(make_pair(cost[e.to], e.to));
}
}
}
return cost[e]; } int cal()
{
int ans=INF;
for(int i=; i<edge_cnt; i+=)
{
edge[i].tag=;
edge[i^].tag=;
ans=min(ans, edge[i].cost+dijkstra(edge[i].from, edge[i].to));
edge[i].tag=;
edge[i^].tag=;
}
return ans==INF? : ans;
} int main()
{
freopen("input.txt", "r", stdin);
int t, a, b, c, n, m;
while(~scanf("%d %d", &n, &m))
{
edge_cnt=;
for(int i=; i<=n; i++) vect[i].clear();
memset(g, 0x7f, sizeof(g)); for(int i=; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
g[b][a]=g[a][b]=min(g[a][b], c);
}
for(int i=; i<=n; i++) //为了去重边
{
for(int j=i+; j<=n; j++)
{
if(g[i][j]<INF)
{
add_node(i, j, g[i][j]);
add_node(j, i, g[i][j]);
}
}
}
int ans=cal();
if(ans) printf("%d\n", ans);
else printf("It's impossible.\n");
}
return ;
}

AC代码

  (3)floyd。dijkstra是枚举删某条边,而floyd是枚举相连的两条边。先理解floyd的思想,穷举每个点k作为中间节点来更新其他点a和b之间的距离,而当某个点未被k枚举到时,是不可能有一条路径将其包含在中间的,它顶多可以作为路径的起点或者终点。利用这点,在未枚举到某点k作为中间点时,可以枚举一下与k相连的两条边,即i->k->j。

  78ms

 #include <bits/stdc++.h>
#define INF 0x7f7f7f7f
#define pii pair<int,int>
#define LL unsigned long long
using namespace std;
const int N=;
int g[N][N], dist[N][N]; int cal(int n) //floyd
{
int ans=INF;
for(int k=; k<=n; k++) //注意枚举顺序。
{
//枚举两条边i->k->j。
for(int i=; i<=n; i++ )
{
if(g[i][k]==INF || k==i) continue;
for(int j=i+; j<=n; j++) //i和j不能相等,才能保证至少3个点。
{
if(g[k][j]==INF || dist[i][j]==INF || k==j ) continue;
int dis=g[i][k] + g[k][j] + dist[i][j];
ans=min(ans, dis);
}
}
for(int i=; i<=n; i++)
{
for(int j=; j<=n; j++)
{
if(dist[i][k]==INF || dist[k][j]==INF) continue;
dist[i][j]=min(dist[i][j], dist[i][k]+dist[k][j]);
}
}
} return ans==INF? : ans;
} int main()
{
freopen("input.txt", "r", stdin);
int t, a, b, c, n, m;
while(~scanf("%d %d", &n, &m))
{
memset(g, 0x7f, sizeof(g));
for(int i=; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
g[b][a]=g[a][b]=min(g[a][b], c);
}
memcpy(dist, g, sizeof(g));
for(int i=; i<=n; i++) dist[i][i]=; int ans=cal(n);
if(ans) printf("%d\n", ans);
else printf("It's impossible.\n");
}
return ;
}

AC代码

HDU 1599 find the mincost route (无向图的最小环)的更多相关文章

  1. HDU 1599 find the mincost route(floyd求最小环 无向图)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1599 find the mincost route Time Limit: 1000/2000 MS ...

  2. hdu 1599 find the mincost route (最小环与floyd算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1599 find the mincost route Time Limit: 1000/2000 MS ...

  3. hdu 1599 find the mincost route(无向图的最小环)

    find the mincost route Time Limit: 1000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  4. hdu 1599 find the mincost route floyd求无向图最小环

    find the mincost route Time Limit: 1000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  5. hdu 1599 find the mincost route 最小环

    题目链接:HDU - 1599 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须 ...

  6. hdoj 1599 find the mincost route【floyd+最小环】

    find the mincost route Time Limit: 1000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  7. HDU 1599 find the mincost route (无向图floyd最小环详解)

    转载请注明出处:http://blog.csdn.net/a1dark 分析:终于弄懂了floyd的原理.以前的理解一直肤浅.所以一做到floyd应用的题.就拙计了.其实floyd的本质DP.利用前K ...

  8. hdu 1599 find the mincost route

    http://acm.hdu.edu.cn/showproblem.php?pid=1599 floyd找最小环. #include <cstdio> #include <cstri ...

  9. hdu 1599 find the mincost route(flyod求最小环)

    Problem Description 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1, ...

随机推荐

  1. 设计模式之Builder模式

    一.感性认识 二.Builder模式 1.定义 一个复杂对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.即构建过程相同,但是子部件却不相同. 2.结构说明 Builder: 创建者接口 ...

  2. HDU4718 The LCIS on the Tree(LCT)

    又是一枚LCT,写一发加深一下对LCT的理解.本题的坑爹之处就在于,它实在是太坑爹了.询问的是树路径上的最长连续上升的子串,考验的是怎么样去维护.一开始的想法是维护三个变量 ls,rs,mxl,分别表 ...

  3. POJ 2182

    #include <iostream> #define MAXN 8005 using namespace std; int _m[MAXN]; int main() { //freope ...

  4. POJ 1491

    #include<iostream> #include<cmath> #include<iomanip> #define MAXN 50 using namespa ...

  5. sql server 存储过程,事务

    1.存储过程,事务 CREATE PROCEDURE Proc_ceshi @id int, ), @returnval int output AS BEGIN SET NOCOUNT ON; Set ...

  6. 消除ComponentOne(C1StudioNet_2013v2) 的注册提示

     以后大家如果遇到还有提示,在License文件里添加:C1.Win.C1Command.C1OutBar, C1.Win.C1Command.4, Version=4.0.20132.19568,  ...

  7. 【OpenCV入门教程之二】 一览众山小:OpenCV 2.4.8组件结构全解析

    转自: http://blog.csdn.net/poem_qianmo/article/details/19925819 本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:ht ...

  8. C#遍历打印机

    #region 获取本机默认打印机名称 ArrayList al1=new ArrayLIst(); private static PrintDocument fPrintDocument = new ...

  9. 网络处理2-异步POST请求和同步请求

    一.异步POST请求 假如请求路径是http://192.168.1.102:8080/MJServer/login,请求参数有2个: username :母鸡 pwd :123 1.POST请求细节 ...

  10. Java:内部类

    1.内部类的定义: 一个内部类可以定义在另一个类里,可以定义在函数里,甚至可以作为一个表达式的一部分. 2.内部类的分类: Java中的内部类共分为四种: 成员内部类member inner clas ...