POJ - 1251
题意&&解法:裸题
ACODE:
//7777777
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l , m , rt << 1
#define rson m+1 , r , rt << 1 | 1
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const double eps = 1e-6;
const int MXN = 1e5 + 7;
const int MXM = 1e5 + 7;
const int MX = 1e4 + 7;
const int maxbit = 18;
const double val = pi/180.0;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
int pre[MX];
int m,n;
int find(int x)
{
if(pre[x] == x) return x;
return pre[x] = find(pre[x]);
}
bool same(int x,int y)
{
return find(x) == find(y);
}
void unionset(int x,int y)
{
int f1 = find(x);
int f2 = find(y);
if(f1 == f2) return;
pre[f1] = f2;
}
struct node
{
int u,v;
int w;
}e[MX];
bool cmp(node a ,node b)
{
return a.w < b.w;
}
void init()
{
for(int i = 1;i <= n;++i) pre[i] = i;
mem(e,0);
m = 0;
}
int kruskal()
{
int ans = 0;
int cont = 0;
sort(e+1,e+1+m,cmp);
for(int i = 1;i <= m;++i)
{
if(same(e[i].u,e[i].v)) continue;
unionset(e[i].u,e[i].v);
cont++;
ans += e[i].w;
if(cont == n-1) break;
}
return ans;
}
int main()
{
while(cin >> n)
{
if(!n) break;
init();
int T = n - 1;
while(T--)
{
char p;
getchar();
cin >> p;
int st = p - 'A' + 1;
int k;
cin >> k;
while(k--){
int ed;
int val;
cin >> p;
cin >> val;
ed = p - 'A' + 1;
e[++m].u = st;
e[m].v = ed;
e[m].w = val;
}
}
int ans = kruskal();
cout << ans << endl;
}
return 0;
}
POJ-1287
题意&&解法:本来也是裸题,唯一坑点在于该题中路的条数被描述为
The number of possible routes is unlimited.
所以就只能xjb开数组范围了
开5e3就过了
ACODE:
//7777777
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l , m , rt << 1
#define rson m+1 , r , rt << 1 | 1
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const double eps = 1e-6;
const int MXN = 1e3 + 7;
const int MXM = 1e3 + 7;
const int MX = 1e2 + 7;
const int maxbit = 18;
const double val = pi/180.0;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
int n,m;
struct node
{
int from,to;
int cost;
}a[5000];
int pre[55];
void init()
{
for(register int i = 1; i <= n; ++i)
pre[i] = i;
}
int found(int x)
{
if(pre[x] == x) return x;
return pre[x] = found(pre[x]);
}
bool same(int x,int y)
{
return found(x) == found(y);
}
void unionset(int x,int y)
{
int f1 = found(x);
int f2 = found(y);
if(f1 == f2) return;
pre[f1] = f2;
}
bool cmp(node a,node b)
{
return a.cost < b.cost;
}
int kruskal()
{
int ans = 0;
int cont = 0;
sort(a+1,a+1+m,cmp);
init();
for(int i = 1; i <= m; ++i)
{
if(same(a[i].from,a[i].to))
continue;
unionset(a[i].from,a[i].to);
ans += a[i].cost;
cont ++;
if(cont == n-1)
break;
}
return ans;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
scanf("%d",&m);
for(int i = 1; i <= m; ++i)
{
scanf("%d %d %d",&a[i].from,&a[i].to,&a[i].cost);
}
int ans;
ans = kruskal();
printf("%d\n",ans);
}
return 0;
}
POJ-2414
题意&&解法:给你一个图让你计算最小生成树,但有些路已经被修好了,所以其权值为0,需提前处理一下。
若用kruskal解决该题,则只需要将那些已经被修好的路提前加入最小生成树集合;
若用prim写,则只需要d[u][v] = d[v][u] = 0;
ACODE:
//7777777
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l , m , rt << 1
#define rson m+1 , r , rt << 1 | 1
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const double eps = 1e-6;
const int MXN = 1e5 + 7;
const int MXM = 1e5 + 7;
const int MX = 1e4 + 7;
const int maxbit = 18;
const double val = pi/180.0;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
int pre[MX];
int n;
struct node
{
int u,v;
int c;
}e[MX];
bool cmp(node a,node b)
{
return a.c < b.c;
}
void init()
{
for(int i = 1;i <= n;++i) pre[i] = i;
}
int find(int x)
{
if(x == pre[x]) return x;
return x = find(pre[x]);
}
bool same(int x,int y)
{
return find(x) == find(y);
}
void unionset(int x,int y)
{
int f1 = find(x);
int f2 = find(y);
if(f1 == f2) return;
pre[f1] =f2;
}
int kruskal()
{
int m = n*n;
int ans = 0;
sort(e,e+m,cmp);
for(int i = 0;i < m;++i)
{
if(same(e[i].u,e[i].v)) continue;
unionset(e[i].u,e[i].v);
ans+=e[i].c;
}
return ans;
}
int main(int argc, char const *argv[])
{
int p = 0;
scanf("%d",&n);
for(int i = 0;i < n;++i)
{
for(int j = 0;j < n;++j)
{
int w;
scanf("%d",&w);
e[p].u = i+1;
e[p].v = j+1;
e[p++].c = w;
}
}
int q;
scanf("%d",&q);
init();
while(q--)
{
int u,v;
scanf("%d %d",&u,&v);
unionset(u,v);
}
int ans = kruskal();
printf("%d\n",ans);
return 0;
}
ZOJ-1586
题意&&解法:该题中在两个点之间连边的耗费是w + val[u] + val[v],所以只需要在建边的时候处理即可。
ACODE:
//7777777
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l , m , rt << 1
#define rson m+1 , r , rt << 1 | 1
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const double eps = 1e-6;
const int MXN = 1e5 + 7;
const int MXM = 1e6 + 7;
const int MX = 1e4 + 7;
const int maxbit = 18;
//const double val = pi/180.0;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
int n,m;
int pre[MX];
int val[MX];
struct node
{
int u,v;
int w;
}e[MXM];
void init()
{
m = 0;
for(int i = 1;i <= n;++i)
pre[i] = i;
}
int find(int x)
{
if(pre[x] == x) return x;
return pre[x] = find(pre[x]);
}
bool same(int x,int y)
{
return find(x) == find(y);
}
void unionset(int x,int y)
{
int f1 = find(x);
int f2 = find(y);
if(f1 == f2) return ;
pre[f1] = f2;
return ;
}
bool cmp(node a,node b)
{
return a.w < b.w;
}
int kruskal()
{
//printf("fuck\n");
int cont = 0;
int ans = 0;
sort(e+1,e+1+m,cmp);
for(int i = 1;i <= m;++i)
{
if(same(e[i].u,e[i].v)) continue;
unionset(e[i].u,e[i].v);
ans += e[i].w;
cont ++;
if(cont == n-1) break;
}
return ans;
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> n;
init();
for(int i = 1;i <= n;++i) cin >> val[i];
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= n;++j)
{
int k;
cin >> k;
if(j <= i) continue;
//printf("fuck\n");
e[++m].u = i;
e[m].v = j;
e[m].w = k + val[i] + val[j];
}
}
//printf("fuck\n");
int ans = kruskal();
//cout << m << endl;
cout << ans << endl;
}
return 0;
}
POJ-2349
题意&&解法:
裸题
ACODE:
//7777777
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l , m , rt << 1
#define rson m+1 , r , rt << 1 | 1
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const double eps = 1e-6;
const int MX = 5e2 + 7;
const int maxbit = 18;
const double val = pi/180.0;
const int INF = 0x3f3f3f3f;
int n,m,k;
int pre[MX];
void init()
{
for(register int i = 0;i < n;++i) pre[i] = i;
}
int found(int x)
{
if(x == pre[x]) return x;
return pre[x] = found(pre[x]);
}
bool same(int x,int y)
{
return found(x) == found(y);
}
void unionset(int x,int y)
{
int f1 = found(x);
int f2 = found(y);
if(f1 == f2) return;
pre[f1] = f2;
}
struct node
{
int from,to;
double cost;
}e[MX*MX];
bool cmp(node a,node b)
{
return a.cost < b.cost;
}
double kruskal()
{
int cont = 0;
double ans = -INF;
init();
sort(e,e+m,cmp);
for(register int i = 0;i < m;++i)
{
if(same(e[i].from,e[i].to)) continue;
if(cont == n - k) break;
ans = max(ans,e[i].cost);
unionset(e[i].from,e[i].to);
cont ++;
}
return ans;
}
double cal(double x1,double y1,double x2,double y2)
{
return sqrt((x1-x2)*(x1-x2) + (y1- y2) * (y1- y2));
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&k,&n);
mem(e,0);
double x[MX],y[MX];
m = n*n;
for(register int i = 0;i < n;++i)
{
scanf("%lf%lf",&x[i],&y[i]);
}
int c = 0;
for(register int i = 0;i < n;++i)
{
for(register int j = 0;j < n;++j)
{
e[c].from = i;
e[c].to = j;
e[c++].cost = cal(x[i],y[i],x[j],y[j]);
}
}
double ans = kruskal();
printf("%.2f\n",ans);
}
return 0;
}
POJ-1715
题意&&解法:
这题有两个值得注意的地方:
ACODE:
#include
#include
#include
#include
#include
#include
#include
#include
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const int MX = 1e3 + 7 ;
const double val = pi/180.0;
const int INF = 0x3f3f3f3f;
double cal(int x1,int y1,int x2,int y2)
{
return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
int n,m;
int pre[MX];
int x[MX];
int y[MX];
int vis[MX][MX];
int p;
struct node
{
int u,v;
double w;
}e[MX*MX];
queue<node>q;
bool cmp(node a,node b)
{
return a.w < b.w;
}
void init()
{
for(int i = 1;i <= n;++i) pre[i] = i;
}
int find(int x){
if(pre[x] == x) return x;
return pre[x] = find(pre[x]);
}
bool same(int x,int y){
return find(x) == find(y);
}
void unionset(int x,int y)
{
int f1 = find(x);
int f2 = find(y);
if(f1 == f2) return;
pre[f1] = f2;
}
void kruskal()
{
sort(e+1,e+1+p,cmp);
for(int i = 1;i <= p;++i)
{
if(same(e[i].u,e[i].v)) continue;
unionset(e[i].u,e[i].v);
q.push({e[i].u,e[i].v,0});
}
return;
}
int main()
{
cin>>n;
m = n*n;
p = 0;
for(int i = 1;i <= n;++i)
cin>>x[i]>>y[i];
for(int i = 1;i <= n;++i)
for(int j = i+1;j <= n;++j)
{
e[++p].u = i;
e[p].v = j;
e[p].w = cal(x[i],y[i],x[j],y[j]);
}
int t;
cin>>t;
init();
while(t--)
{
int u,v;
cin>>u>>v;
unionset(u,v);
}
kruskal();
//if(q.empty()) cout<
while(!q.empty())
{
node x = q.front();
q.pop();
cout<<x.u<<' '<<x.v<<endl;
}
return 0;
}
POJ-1258
题意&&解法:裸题
ACODE:
//7777777
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson l , m , rt << 1
#define rson m+1 , r , rt << 1 | 1
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const double eps = 1e-6;
const int MXN = 1e3 + 7;
const int MXM = 1e3 + 7;
const int MX = 1e2 + 7;
const int maxbit = 18;
const double val = pi/180.0;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
int n;
int cost[MX][MX];
int mincost[MX];
int used[MX];
int prim()
{
for(int i = 0;i < n;++i)
{
mincost[i] = INF;
used[i] = 0;
}
mincost[0] = 0;
int ans = 0;
while(1)
{
int v = -1;
for(int u = 0;u < n;++u)
{
if(!used[u] && (v == -1||mincost[u] < mincost[v]))
v = u;
}
if(v == -1) break;
used[v]=1;
ans +=mincost[v];
for(int u = 0;u < n;++u)
{
mincost[u] = min(mincost[u],cost[v][u]);
}
}
return ans;
}
int main()
{
while(~scanf("%d",&n))
{
for(int i = 0;i < n;++i)
for(int j = 0;j < n;++j)
scanf("%d",&cost[i][j]);
int ans = prim();
printf("%d\n",ans);
}
}
POJ-1679
题意&&解法:
给你一个图,让你判断其最小生成树是否唯一(即是否存在多个耗费相同且都最小的生成树)
性质:次小生成树可由最小生成树换一条边得到
所以我们可以求其次小生成树,若和最小生成树耗费相同,则最小生成树不唯一。
我们先跑一遍kruskal记录下最小生成树的每一条边,然后再跑n-1次kruskal依次删除这n-1条边后(即遇到该边就跳过)的最小生成树(次小生成树)。坑点:此时还要判断一下是否能生成树。
ACODE:
#include
#include
#include
#include
#include
#include
#include
#include
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const double pi = 3.1415926535;
const int MX = 1e4 + 7 ;
const double val = pi/180.0;
const int INF = 0x3f3f3f3f;
int pre[MX];
int edge[MX];
int n,m;
struct node
{
int u,v;
int w;
int id;
}e[MX];
bool cmp(node a,node b)
{
return a.w < b.w;
}
void init()
{
for(int i = 1;i <= n;++i) pre[i] = i;
}
int find(int x)
{
if(pre[x] == x) return x;
return x = find(pre[x]);
}
bool same(int x,int y)
{
return find(x) == find(y);
}
void unionset(int x,int y)
{
int f1 = find(x);
int f2 = find(y);
if(f1 == f2) return ;
pre[f1] =f2;
}
int kruskal()
{
int p = 0;
int ans = 0;
init();
sort(e,e+m,cmp);
for(int i = 1;i <= m;++i)
{
if(same(e[i].u,e[i].v)) continue;
unionset(e[i].u,e[i].v);
ans += e[i].w;
edge[++p] = e[i].id;
}
return ans;
}
int kruskal2(int K)
{
int cont = 0;
int ans = 0;
init();
sort(e,e+m,cmp);
for(int i = 1;i <= m;++i)
{
if(e[i].id == K) continue;
if(same(e[i].u,e[i].v)) continue;
unionset(e[i].u,e[i].v);
ans += e[i].w;
cont++;
}
if(cont != n-1) return -1;
return ans;
}
int main(int argc, char const *argv[])
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i = 1;i <= m;++i)
{
cin>>e[i].u>>e[i].v>>e[i].w;
e[i].id = i;
}
int ans = kruskal();
int flag = 0;
for(int i = 1;i <= n-1;++i)
{
int k = kruskal2(edge[i]);
if(k == ans){
flag = 1;
break;
}
}
if(flag){
printf("Not Unique!\n");
}
else printf("%d\n",ans);
}
return 0;
}```