↓ Skip to main content
  1. Posts/

poj 1751 Highways (最小生成树,空间卡常数有毒啊)

·607 words·2 mins
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

poj1751题目链接

题意:一开始有一些边,然后添加一些边,使得代价之和最小。

思路:先把给定的边merge掉。。然后计算其余可以添加的边。。。接下来就是最小生成树。。。

然而因为多开了一个750*750的数组空间被卡了常。。。毫无人性。。。。

代码实现
  1/* ***********************************************
  2Author :111qqz
  3Created Time :2016年07月13日 星期三 19时53分29秒
  4File Name :code/poj/1751.cpp
  5 ************************************************ */
  6
  7#include <cstdio>
  8#include <cstring>
  9#include <iostream>
 10#include <algorithm>
 11#include <vector>
 12#include <queue>
 13#include <set>
 14#include <map>
 15#include <string>
 16#include <cmath>
 17#include <cstdlib>
 18#include <ctime>
 19#define fst first
 20#define sec second
 21#define lson l,m,rt<<1
 22#define rson m+1,r,rt<<1|1
 23#define ms(a,x) memset(a,x,sizeof(a))
 24typedef long long LL;
 25#define pi pair < int ,int >
 26#define MP make_pair
 27
 28using namespace std;
 29const double eps = 1E-8;
 30const int dx4[4]={1,0,0,-1};
 31const int dy4[4]={0,-1,1,0};
 32const int inf = 0x3f3f3f3f;
 33const int N=755;
 34int n;
 35int m;
 36int om;
 37pi ans[N*N];
 38bool conc[N*N];
 39int f[N];
 40struct Edge
 41{
 42    int u,v;
 43    double w;
 44
 45    bool operator < (Edge b)const
 46    {
 47	return w<b.w;
 48    }
 49}edge[N*N];
 50
 51
 52
 53struct point
 54{
 55    double  x,y;
 56
 57    void input()
 58    {
 59	scanf("%lf%lf",&x,&y);
 60    }
 61
 62    double dis( point b)
 63    {
 64	double res ;
 65	res = (x-b.x)*(x-b.x)+(y-b.y)*(y-b.y);
 66	return sqrt(res);
 67    }
 68}p[N];
 69
 70void init()
 71{
 72    for ( int i = 1 ; i <= n ; i++) f[i] = i;
 73}
 74
 75int root ( int x)
 76{
 77    if (x!=f[x] ) f[x] = root (f[x]);
 78    return f[x];
 79}
 80
 81void merge( int x,int y)
 82{
 83    int rx = root (x);
 84    int ry = root (y);
 85    if (rx==ry) return ;
 86    f[rx] = ry;
 87}
 88int main()
 89{
 90#ifndef  ONLINE_JUDGE
 91    freopen("code/in.txt","r",stdin);
 92#endif
 93
 94    cin>>n;
 95    init();
 96    for ( int i = 1 ; i <= n ; i++) p[i].input();
 97    cin>>m;
 98    om = m;
 99    int cnt = 0 ;
100    for ( int i = 1 ; i <= m ; i++)
101    {
102	int u,v;
103	scanf("%d%d",&u,&v);
104	if (root(u)==root(v)) continue;
105	merge(u,v);
106	cnt++;
107    }
108
109    m = 0 ;
110    for ( int i = 1 ; i <= n ; i++)
111	for ( int j = 1 ; j <= n ; j++)
112	    if (i<j)
113	    {
114		m++;
115		edge[m].u =i;
116		edge[m].v = j ;
117		edge[m].w = p[i].dis(p[j]);
118	    }
119
120    sort(edge+1,edge+m+1);
121    double mst = 0 ;
122    int num = 0 ;
123    for ( int i = 1; i <= m ; i++)
124    {
125	int u = edge[i].u;
126	int v = edge[i].v;
127	double w = edge[i].w;
128	if (cnt>=n-1) break;
129	if (root(u)==root(v)) continue;
130	//	    cout<<"u:"<<u<<" v:"<<v<<" w:"<<w<<endl;
131	merge(u,v);
132	cnt++;
133	num++;
134	mst+=w;
135	ans[num]=make_pair(u,v);
136    }
137    //	cout<<"cnt:"<<cnt<<endl;
138    sort(ans+1,ans+num+1);
139
140    for ( int i = 1 ;i <= num ; i++)
141	cout<<ans[i].fst<<" "<<ans[i].sec<<endl;
142
143
144
145#ifndef ONLINE_JUDGE
146    fclose(stdin);
147#endif
148    return 0;
149}

Related

poj 1679 The Unique MST (判断mst的唯一性,次小生成树)

·548 words·2 mins
poj1679 题意:问最小生成树是否唯一。。 思路:求一下次小生成树。。。如果无解,或者次小生成树的权值之和和最小生成树的权值之和不同,那么唯一,否则不唯一。1A 代码实现 1/* *********************************************** 2Author :111qqz 3Created Time :2016年07月12日 星期二 16时16分52秒 4File Name :code/poj/1679.cpp 5************************************************ */ 6#include <cstdio> 7#include <cstring> 8#include <iostream> 9#include <algorithm> 10#include <vector> 11#include <queue> 12#include <set> 13#include <map> 14#include <string> 15#include <cmath> 16#include <cstdlib> 17#include <ctime> 18#define fst first 19#define sec second 20#define lson l,m,rt<<1 21#define rson m+1,r,rt<<1|1 22#define ms(a,x) memset(a,x,sizeof(a)) 23typedef long long LL; 24#define pi pair < int ,int > 25#define MP make_pair 26using namespace std; 27const double eps = 1E-8; 28const int dx4[4]={1,0,0,-1}; 29const int dy4[4]={0,-1,1,0}; 30const int inf = 0x3f3f3f3f; 31const int N=105; 32int n,m; 33int ans; 34int f[N]; 35struct Edge 36{ 37 int u,v,w; 38 int in; 39 void input() 40 { 41 scanf("%d%d%d",&u,&v,&w); 42 } 43 bool operator < (Edge b)const 44 { 45 return w<b.w; 46 } 47}edge[N*N]; 48void init() 49{ 50 for ( int i = 1 ; i <= n ; i++) f[i] = i; 51} 52int root ( int x) 53{ 54 if (x!=f[x]) f[x] = root(f[x]); 55 return f[x]; 56} 57void merge( int x,int y) 58{ 59 int rx = root(x); 60 int ry = root(y); 61 if (rx==ry) return ; 62 f[rx] = ry; 63} 64void kruskal( int k) 65{ 66 for ( int i = 1 ; i <= n; i++) f[i] = i; 67 int cnt = 0 ; 68 int cur = 0 ; 69 for ( int i = 1; i <= m ; i++) 70 { 71 int u = edge[i].u; 72 int v = edge[i].v; 73 int w = edge[i].w; 74 if (i==k) continue; 75 if (root(u)==root(v)) continue; 76 merge(u,v); 77 cnt++; 78 cur+=w; 79 if (cnt>=n-1) break; 80 } 81 // cout<<"cnt:"<<cnt<<endl; 82 if (cnt<n-1) return ; 83 ans = min(ans,cur); 84} 85int main() 86{ 87 #ifndef ONLINE_JUDGE 88 freopen("code/in.txt","r",stdin); 89 #endif 90 int T; 91 scanf("%d",&T); 92 while (T--) 93 { 94 scanf("%d%d",&n,&m); 95 init(); 96 for ( int i = 1; i <= m ; i++) edge[i].input(); 97 sort(edge+1,edge+m+1); 98 int cnt = 0 ; 99 int mst = 0 ; 100 for ( int i = 1 ; i <= m ; i++) 101 { 102 int u = edge[i].u; 103 int v = edge[i].v; 104 int w = edge[i].w; 105 if (root(u)==root(v)) continue; 106 edge[i].in = 1; 107 merge(u,v); 108 cnt++; 109 mst+=w; 110 } 111 ans = inf; 112 for ( int i = 1 ; i <= m ; i++) 113 { 114 if (edge[i].in==0) continue; 115 //cout<<"i:"<<i<<endl; 116 kruskal(i); 117 } 118 // cout<<"mst:"<<mst<<endl; 119 // cout<<"ans:"<<ans<<endl; 120 if (ans==inf) 121 { 122 printf("%d\n",mst); 123 }else 124 { 125 if (ans==mst) puts("Not Unique!"); 126 else printf("%d\n",mst); 127 } 128 } 129 #ifndef ONLINE_JUDGE 130 fclose(stdin); 131 #endif 132 return 0; 133}

ural 1416. Confidential (次小生成树模板题)

·730 words·2 mins
URAL1416 题意:次小生成树模板题 思路:用Kruskal求最小生成树,标记用过的边。求次小生成树时,依次枚举用过的边,将其去除后再求最小生成树,得出所有情况下的最小的生成树就是次小的生成树。复杂度o(m2)。。。貌似有其他优化。。。

hdu 4607 Park Visit (树的直径,推公式)

·748 words·2 mins
hdu4607题目链接 题意:给出一棵树。。。边权都为1. m个查询。。每个查询给一个k,表示只访问k个点。。。问每次的最小路径和是多少。。。 思路:我们发现。。会使路径和变大的一个不利因素是折返。。也就是访问某景点后。。必须要回去才能继续前进。。这样的距离是2倍。。那为了使得路径和尽可能小。。我们就尽量不要访问这样的点。。。而不是这样的点一定在直径上。。。以及我们还发现。。。不在直径上的点。。 。。不管深度如何(深度的意思是说,与和该点最近的直径上的点的距离),距离的贡献是一样的。。都是2倍。。所以我们可以推出一个公式。。。如果树的直径是d,那么k<=d+1的时候,答案为k-1,否则答案为d+(k-d-1)*2。。。

poj 3310 Caterpillar (树的直径+并查集判环+dfs判断连通性)

poj 3310 题目链接 题意:给出一个无向图,问是否满足:连通,并且无环,并且能找到一条路径,图中所有的顶点要么在这条路径上,要么与这条路径上的顶点相邻。 思路:一个一个来。连通的话任意起点开始跑一遍 dfs?开一个 bool 数组标记走过的点,最后扫一遍,看是否有点没走过。

hdu 4514 湫湫系列故事——设计风景线 (无向图并查集判环+非联通图的最长路径)

·897 words·2 mins
hdu 4514 题意:给出一个无向图,问是否有环,有的话输出 YES。如果没有环的话,输出最长路径。 思路:无向图判环用并查集就好。关于最长路径这里,一开始以为就是树的直径。 但是需要注意的是,题目并没有保证图一定是联通的,所以 gg 了。