描述

  给定一张无向图,求图中一个至少包含 3 个点的环,环上的节点不重复,并且环上的边的长度之和最小。该问题称为无向图的最小环问题。在本题中,你需要输出最小环的方案,若最小环不唯一,输出任意一个均可。若无解,输出 No solution.。图的节点数不超过 100 。

输入

第一行两个正整数 n,m 表示点数和边数。

接下来 m 行,每行三个正整数 x,y,z ,表示节点 x,y 之间有一条长度为 z 的边。

输出

输出一个最小环的方案:按环上顺序输出最小环上的点。若最小环不唯一,输出任意一个均可。若无解,输出 No solution.

样例输入

5 7
1 4 1
1 3 300
3 1 10
1 2 16
2 3 100
2 5 15
5 3 20

样例输出

1 3 5 2

标签

CEOI1999

题解

  其实这道题可以用Floyd。

  容易知道,树加上一条非树边可以形成环。利用这个性质,我们可以先求出一棵最小生成树,然后通过枚举每一条非树边求出加上它之后所形成的环的大小并尝试更新答案。输出方案时直接在最小生成树上暴力跳就行了。时间复杂度O(mlogn)。

  代码:

#include<bits/stdc++.h>
using namespace std;
#define gc getchar
template<typename T>void read(T&cn){
char c;int sig=;
while(!isdigit(c=gc())) if(c=='-') sig=-;cn=c-;
while( isdigit(c=gc())) cn=cn*+c-;cn*=sig;
}
#define N 100010
#define INF 0x3f3f3f3f
int n,m;
namespace T{
int num,f[N];
struct node{
int u,v,w,nxt;
}e[N<<];
void add(int u,int v,int w){
e[++num]=(node){u,v,w,f[u]};f[u]=num;
e[++num]=(node){v,u,w,f[v]};f[v]=num;
}
//build graph
int dep[N],dis[N],faz[N],siz[N],son[N],top[N];
void dfs1(int u,int fa,int d){
dep[u]=d;faz[u]=fa;siz[u]=;
for(int i=f[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa) continue;
dis[v]=dis[u]+e[i].w;dfs1(v,u,d+);siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int st){
top[u]=st;
if(!son[u]) return;dfs2(son[u],st);
for(int i=f[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==faz[u]||v==son[u]) continue;
dfs2(v,v);
}
}
int LCA(int x,int y){
int xx=top[x],yy=top[y];
while(xx^yy){
if(dep[xx]<dep[yy]){swap(xx,yy);swap(x,y);}
x=faz[xx];xx=top[x];
}
return dep[x]<dep[y]?x:y;
}
//tree dissection
}
namespace G{
struct node{
int u,v,w;
}e[N];
bool operator < (node a,node b){return a.w<b.w;}
//graph
int fa[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int merge(int x,int y){
int xx=find(x),yy=find(y);
if(xx==yy) return ;
fa[xx]=yy; return ;
}
//Disjoint-Set
int vis[N];
void kruskal(){
sort(e+,e+m+);int cnt=;
for(int i=;i<=n;i++) fa[i]=i;
for(int i=;i<=m;i++){
int u=e[i].u,v=e[i].v;
if(merge(u,v)){cnt++;vis[i]=;T::add(u,v,e[i].w);}
if(cnt==n-) break;
}
}
//mst
int sum=INF,a,b,c;
#define pb push_back
vector<int>ans;
void work(){
read(n);read(m);
for(int i=;i<=m;i++){read(e[i].u);read(e[i].v);read(e[i].w);}
kruskal();T::dfs1(,,);T::dfs2(,);
for(int i=;i<=m;i++){
if(vis[i]) continue;
int u=e[i].u,v=e[i].v;
if(T::dep[u]<T::dep[v]) swap(u,v);
if(T::faz[u]==v||u==v) continue;
int lca=T::LCA(u,v),tmp=T::dis[u]+T::dis[v]-(T::dis[lca]<<)+e[i].w;
if(sum>tmp){sum=tmp;a=u,b=v;c=lca;}
}
if(sum==INF){puts("No solution.");exit();}
while(a^c){printf("%d ",a);a=T::faz[a];}printf("%d ",c);
while(b^c){ans.pb(b);b=T::faz[b];}
if(ans.size()) for(int i=ans.size()-;~i;i--) printf("%d ",ans[i]);
}
}
int main(){
G::work();
return ;
}

WOJ#3836 Sightseeing Trip的更多相关文章

  1. URAL 1004 Sightseeing Trip(最小环)

    Sightseeing Trip Time limit: 0.5 secondMemory limit: 64 MB There is a travel agency in Adelton town ...

  2. poj1734 Sightseeing trip【最小环】

    Sightseeing trip Time Limit: 1000MS   Memory Limit: 65536K Total Submissions:8588   Accepted:3224   ...

  3. 「LOJ#10072」「一本通 3.2 例 1」Sightseeing Trip(无向图最小环问题)(Floyd

    题目描述 原题来自:CEOI 1999 给定一张无向图,求图中一个至少包含 333 个点的环,环上的节点不重复,并且环上的边的长度之和最小.该问题称为无向图的最小环问题.在本题中,你需要输出最小环的方 ...

  4. poj 1734 Sightseeing trip判断最短长度的环

    Sightseeing trip Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5590   Accepted: 2151 ...

  5. 【poj1734】Sightseeing trip

    Sightseeing trip Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8520   Accepted: 3200 ...

  6. Ural 1004 Sightseeing Trip

    Sightseeing Trip Time Limit: 2000ms Memory Limit: 16384KB This problem will be judged on Ural. Origi ...

  7. POJ 1734:Sightseeing trip

    Sightseeing trip Time Limit: 1000MS Memory Limit: 65536K Total Submissions: Accepted: Special Judge ...

  8. [CEOI1999]Sightseeing trip(Floyed)

    [CEOI1999]Sightseeing trip Description There is a travel agency in Adelton town on Zanzibar island. ...

  9. 「POJ1734」Sightseeing trip

    「POJ1734」Sightseeing trip 传送门 这题就是要我们求一个最小环并且按顺序输出一组解. 考虑 \(O(n^3)\) 地用 \(\text{Floyd}\) 求最小环: 考虑 \( ...

随机推荐

  1. dd命令注意:dd:unrecognized operand 'if'

    如果是 idd if=boot.bin 在等号两边不要有空格

  2. python 7行代码实现微信机器人自动回复

    首先 需要去 图灵 网站注册 获取api_key 先上代码 from wxpy import * bot = Bot() tuling = Tuling(api_key='你的api_key') @b ...

  3. 【bzoj4552】【Tjoi2016&Heoi2016】【NOIP2016模拟7.12】排序

    题目 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次 ...

  4. 面试题常考&必考之--js中的难点!!!原型链,原型(__proto__),原型对象(prototype)结合例子更易懂

    1>首先,我们先将函数对象认识清楚: 补充snow的另一种写法: var snow =function(){}; 2>其次:就是原型对象 每当我们定义一个函数对象的时候,这个对象中就会包含 ...

  5. 【bzoj2427】【软件安装】tarjan缩点+树形依赖背包

    (上不了p站我要死了,侵权度娘背锅) Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上, ...

  6. [CF1177B]Digits Sequence (Hard Edition)题解

    一个简单的模拟,首先先计算当前是几位数,然后根据几位数推断当前的数是什么,然后求出该位即可 #include <cstdio> int main(){ long long k; scanf ...

  7. php开发IDE选择

    优先选择Netbeans,理由如下:: 1.ZendStudio有的方便特性Netbeans也提供,如:ctrl+f5也支持ctrl+shift+r的文件选择功能,[git | svn]团队代码管理. ...

  8. 【CF1249F】Maximum Weight Subset(贪心)

    题意:给定一棵n个点带点权的树,要求从中选出一个点集,使得这些点两两之间距离都大于K,求最大点权和 n,K<=2e2,1<=a[i]<=1e5 思路:树形DP显然可做,极限是n方,然 ...

  9. 清北学堂算法&&数据结构DAY1——知识整理

    简述: 今天主要讲分治(主要是二分).倍增.贪心.搜索,还乱入了爬山算法和模拟退火(汗...) 一.分(er)治(fen): 二分是个在OI中广泛运用的思想,随便举些例子,就足以发现二分的运用的广泛性 ...

  10. js判断浏览器的类型

    我们很多时候都需要判断浏览器,下面就是一些常用的判断 var ua = navigator.userAgent.toLowerCase(); //用来判断移动端类型 var isWeixin = /M ...