HDU 1599 find the mincost route (无向图的最小环)
题意:
给一个带权无向图,求其至少有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 (无向图的最小环)的更多相关文章
- 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 ...
- 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 ...
- hdu 1599 find the mincost route(无向图的最小环)
find the mincost route Time Limit: 1000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- 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 ...
- hdu 1599 find the mincost route 最小环
题目链接:HDU - 1599 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须 ...
- 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 ...
- HDU 1599 find the mincost route (无向图floyd最小环详解)
转载请注明出处:http://blog.csdn.net/a1dark 分析:终于弄懂了floyd的原理.以前的理解一直肤浅.所以一做到floyd应用的题.就拙计了.其实floyd的本质DP.利用前K ...
- hdu 1599 find the mincost route
http://acm.hdu.edu.cn/showproblem.php?pid=1599 floyd找最小环. #include <cstdio> #include <cstri ...
- hdu 1599 find the mincost route(flyod求最小环)
Problem Description 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1, ...
随机推荐
- HDU 4022 Bombing(stl,map,multiset,iterater遍历)
题目 参考了 1 2 #define _CRT_SECURE_NO_WARNINGS //用的是STL中的map 和 multiset 来做的,代码写起来比较简洁,也比较好容易理解. ...
- iOS视频压缩
// // ViewController.m // iOS视频测试 // // Created by apple on 15/8/19. // Copyright (c) 2015年 tqh. All ...
- flume-ng+Kafka+Storm+HDFS 实时系统搭建
转自:http://www.tuicool.com/articles/mMrQnu7 一 直以来都想接触Storm实时计算这块的东西,最近在群里看到上海一哥们罗宝写的Flume+Kafka+Storm ...
- Linux下TOmcat调试命令
1.显示linux系统的环境变量:env命令,会显示JAVA_HOME,Catalina,CLASSPATH等系统变量 2.
- Outlook与Hotmail的设置
最近研究邮件备份,首先要使用客户端下载邮件,碰到不少问题:1. HOTMAIL GMAIL SINA的POP/IMAP默认居然都是关闭的,必须改成开放才行. GMAIL改成开放以后还是没有成功,好像还 ...
- Spring笔记——配置Hibernate框架事务
原文:http://www.iteye.com/topic/1123347 Spring配置文件中关于事务配置总是由三个组成部分,DataSource.TransactionManager和代理机制这 ...
- Struts2笔记——初次框架配置
1.Struts2简介 Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架.其全新的Struts 2的体系结构与S ...
- 关于html5与jsp页面同样的html代码展示的页面效果不一样的问题
原文:关于html5与jsp页面同样的html代码展示的页面效果不一样的问题 html5默认的声明为 <!DOCTYPE html> jsp默认的声明头部为 <%@ page con ...
- SRM 620 DIV1 L2
题意:有n个等长的string(设string的长度为m),string中的字符从'A'到'Z',容许对m列执行稳定的排序操作,问说是否能通过这m种操作将这n个string调整成对应的顺序. 题解: ...
- Linux系统添加硬盘设备(磁盘分区-格式化-挂载-使用)
当全新安装了一块新的硬盘设备后,为了更充分.更安全的利用硬盘空间首先要进行磁盘的分区, 然后格式化,最后挂载使用. 实例:对新添加的硬盘设备进行分区.格式化并挂载到/newFS目录. 第一步:在vmw ...