题意:

  给一个带权无向图,求其至少有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. 就地交叉数组元素[a1a2b1b2]->[a1b1a2b2]

    问题描述: If [a1,a2,a3...,an,b1,b2...bn] is given input change this to [a1,b1,a2,b2.....an,bn] , solutio ...

  2. POJ 2549

    Sumsets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8235   Accepted: 2260 Descripti ...

  3. API 版本控制

    http://www.oschina.net/translate/introduction-to-web-api-versioning

  4. NoSQL数据库有哪些

    NoSQL太火,冒出太多产品了,保守估计也成百上千了. 互联网公司常用的基本集中在以下几种,每种只举一个比较常见或者应用比较成功的例子吧. 1. In-Memory KV Store : Redis ...

  5. php 实现树形结构

    <?phpclass Tree{ private $OriginalList; public $pk;//主键字段名 public $parentKey;//上级id字段名 public $ch ...

  6. VCL定义和使用CM_Message的原因(主要是内部控制,同时可简化参数传递,还可截住消息,统一走消息路线,还可省内存)

    内部控制是指,做了某些操作后产生某些效果,但是Windows系统本身不提供这样的消息,应此不得不自定义.比如父窗口改变了字体,那么所有子窗口也都应该改变字体,至少也得通知一下它们,让子控件自己决定是否 ...

  7. Java笔记——JavaMail发送邮件

    1.JavaMail概述  Java Mail是由SUN公司提供的专门针对邮件的API,主要Jar包:mail.jar.activation.jar. ======================== ...

  8. AlarmManager.RTC和ELAPSED_REALTIME的区别

    AlarmManager.RTC,硬件闹钟,不唤醒手机(也可能是其它设备)休眠:当手机休眠时不发射闹钟. AlarmManager.RTC_WAKEUP,硬件闹钟,当闹钟发躰时唤醒手机休眠: Alar ...

  9. SQL Agent Job ->> 通过sys.sysprocesses的program_name字段来定位对应的Job

    ;WITH T AS ( SELECT 'SQLAgent - TSQL JobStep (Job 0x'+ ),)),) + ' : Step ' + )) + ')' filter, j.job_ ...

  10. SpringBoot配置属性之Server

    SpringBoot配置属性系列 SpringBoot配置属性之MVC SpringBoot配置属性之Server SpringBoot配置属性之DataSource SpringBoot配置属性之N ...