whu Problem 1566 - C - Spanning Tree(最小生成树+处理)
Problem 1566 - C - Spanning Tree
Time Limit: 1000MS Memory Limit: 65536KB
Total Submit: 271 Accepted: 54 Special Judge: No
Total Submit: 271 Accepted: 54 Special Judge: No
Description
You are given a graph with N nodes and M edges.
Then every time you are required to add an additional edge with weight Wi connecting the node Ai and Bi in the graph, and then calculate the sum of the edges’ weight of the Minimum Spanning Tree of the current graph. You’ll be asked to complete the mission for Q times.
The Minimum Spanning Tree of a graph is defined to be a set of N - 1 edges which connects all the N nodes of the graph and the sum of all the edges is as small as possible.
It's guaranteed that the graph is connected.
Input
First line of each case contains three numbers N , M and Q.(1 ≤ N,Q ≤ 1000, 1 ≤ M ≤ 100000 ,)
The following M lines contains three numbers Ai , Bi and Wi.( 1 ≤ Ai, Bi ≤ 1000, 1 ≤ Wi≤ 100000).
The last Q lines of this case contains three numbers Ai , Bi and Wi. ( 1 <= Ai, Bi <= 1000, 1 ≤ Wi≤ 100000 ).
The following M lines contains three numbers Ai , Bi and Wi.( 1 ≤ Ai, Bi ≤ 1000, 1 ≤ Wi≤ 100000).
The last Q lines of this case contains three numbers Ai , Bi and Wi. ( 1 <= Ai, Bi <= 1000, 1 ≤ Wi≤ 100000 ).
Output
Output the answer in a single line for each case.
Sample Input
3 3 3
2 1 8
3 1 4
1 2 6
1 2 4
2 3 1
1 1 4
3 3 3
2 1 7
3 2 8
3 3 6
1 3 3
2 2 3
2 2 3
2 1 8
3 1 4
1 2 6
1 2 4
2 3 1
1 1 4
3 3 3
2 1 7
3 2 8
3 3 6
1 3 3
2 2 3
2 2 3
Sample Output
8
5
5
10
10
10
5
5
10
10
10
传送门:http://acm.whu.edu.cn/land/problem/detail?problem_id=1566
题意:给你n个点和m条边,先让你求最小生成树,然后q次添加边操作每次添加一条边,问每次添加后最小生成树的值。
思路:考虑n,m的范围,添加边直接跑最小生成树时间复杂度为n*mlogm,会超时,不过也有人稍微做下处理水过去的,这数据做的,我们的方法是把每次跑次最小生成树的n-1条边储存,每次添加都是上次的n-1条边基础上,总和就是n条边,时间复杂度就是n*n*logn。
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<iostream>
#define LL long long
using namespace std;
const int MAXN=1005;//最大点数
const int MAXM=100005;//最大边数
int F[MAXN];//并查集使用
struct Edge
{
int u,v,w;
} edge[MAXM],yu[MAXM]; //存储边的信息,包括起点/终点/权值
int tol;//边数,加边前赋值为0
void addedge(int u,int v,int w)
{
edge[tol].u=u;
edge[tol].v=v;
edge[tol++].w=w;
}
bool cmp(Edge a,Edge b)
{
//排序函数,讲边按照权值从小到大排序
return a.w<b.w;
}
int find(int x)
{
if(F[x]==-1)return x;
else return F[x]=find(F[x]);
}
int Kruskal(Edge edge1[],int ge,int n)//传入点数,返回最小生成树的权值,如果不连通返回-1
{
memset(F,-1,sizeof(F));
sort(edge1,edge1+ge,cmp);
int cnt=0;//计算加入的边数
int ans=0;
for(int i=0; i<ge; i++)
{
int u=edge1[i].u;
int v=edge1[i].v;
int w=edge1[i].w;
int t1=find(u);
int t2=find(v);
if(t1!=t2)
{
yu[cnt].u=u;
yu[cnt].v=v;
yu[cnt].w=w;
ans+=w;
F[t1]=t2;
cnt++;
}
if(cnt==n-1)break;
}
if(cnt<n-1)return -1;//不连通
else return ans;
}
int main()
{
// freopen("in.txt","r",stdin);
int n,m,q,ai,bi,wi;
while(~scanf("%d%d%d",&n,&m,&q))
{
tol = 0;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&ai,&bi,&wi);
addedge(ai,bi,wi);
addedge(bi,ai,wi);
}
int ans = Kruskal(edge,tol,n);
for(int i=0; i<q; i++)
{
scanf("%d%d%d",&ai,&bi,&wi);
yu[n-1].u=ai;
yu[n-1].v=bi;
yu[n-1].w=wi;
yu[n].u=bi;
yu[n].v=ai;
yu[n].w=wi;
ans = Kruskal(yu,n,n);
printf("%d\n",ans);
}
}
return 0;
}
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<iostream>
#define LL long long
using namespace std;
const int MAXN=1005;//最大点数
const int MAXM=100005;//最大边数
int F[MAXN];//并查集使用
struct Edge
{
int u,v,w;
} edge[MAXM],yu[MAXM]; //存储边的信息,包括起点/终点/权值
int tol;//边数,加边前赋值为0
void addedge(int u,int v,int w)
{
edge[tol].u=u;
edge[tol].v=v;
edge[tol++].w=w;
}
bool cmp(Edge a,Edge b)
{
//排序函数,讲边按照权值从小到大排序
return a.w<b.w;
}
int find(int x)
{
if(F[x]==-1)return x;
else return F[x]=find(F[x]);
}
int Kruskal(Edge edge1[],int ge,int n)//传入点数,返回最小生成树的权值,如果不连通返回-1
{
memset(F,-1,sizeof(F));
sort(edge1,edge1+ge,cmp);
int cnt=0;//计算加入的边数
int ans=0;
for(int i=0; i<ge; i++)
{
int u=edge1[i].u;
int v=edge1[i].v;
int w=edge1[i].w;
int t1=find(u);
int t2=find(v);
if(t1!=t2)
{
yu[cnt].u=u;
yu[cnt].v=v;
yu[cnt].w=w;
ans+=w;
F[t1]=t2;
cnt++;
}
if(cnt==n-1)break;
}
if(cnt<n-1)return -1;//不连通
else return ans;
}
int main()
{
// freopen("in.txt","r",stdin);
int n,m,q,ai,bi,wi;
while(~scanf("%d%d%d",&n,&m,&q))
{
tol = 0;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&ai,&bi,&wi);
addedge(ai,bi,wi);
addedge(bi,ai,wi);
}
int ans = Kruskal(edge,tol,n);
for(int i=0; i<q; i++)
{
scanf("%d%d%d",&ai,&bi,&wi);
yu[n-1].u=ai;
yu[n-1].v=bi;
yu[n-1].w=wi;
yu[n].u=bi;
yu[n].v=ai;
yu[n].w=wi;
ans = Kruskal(yu,n,n);
printf("%d\n",ans);
}
}
return 0;
}

浙公网安备 33010602011771号