151006 T2
题目背景
题目描述
输入格式
输入第一行三个整数 n,m,k (0≤k≤106)。
接下来 m 行,每行三个整数 x,y,v ,描述一条权值为 v 的边 (x,y)。
输出格式
输出一行一个整数,表示答案。
样例数据 1
备注
【数据范围】
8分的数据:1≤n≤8,m≤100
12分的数据:1≤n≤50,m≤2000
18分的数据:1≤n≤200,m≤10000
26分的数据:1≤n≤1000,m≤105
36分的数据:1≤n≤1000,m≤106
分析:
做法同次小生成树
建最小生成树,预处理出每俩点间最大的边(因为n<=1000 故不需要倍增) 然后用新边替换
最小生成树用prim(O(n^2))
我用的克鲁斯卡尔 (O(m*log m))此题更慢
代码有错 没调试出来 只有80分(我sb了 还用的倍增 代码复杂度升高)
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int n,m,k;
int first[10001];
int jump[10001][11];
int minn[10001][11];
int v[10001];
int dad[10001];
int p[10001];
int fa[10001];
int size,root,num;
int maxx;
int que[10001];
int deep[10001];
int answer,sum;
struct node1
{
int next;
int to;
};
node1 side[10001];
struct node
{
int len;
int to;
int from;
};
node bian[3000002];
int getdad(int x)
{
if(dad[x]==x) return x;
dad[x]=getdad(dad[x]);
return dad[x];
}
void inser(int a,int b,int c)
{
bian[++size].to=b;
bian[size].len=c;
bian[size].from=a;
}
void inser1(int a,int b)
{
side[++num].to=b;
side[num].next=first[a];
first[a]=num;
}
bool comp(const node &a,const node &b)
{
return a.len<b.len;
}
int read()
{
int k=0,f=1;
char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {k=k*10+(c-'0'); c=getchar();}
return k*f;
}
void build()
{
int i,j,u;
int s,t;
root=bian[p[1]].from;
fa[bian[p[1]].to]=root;
jump[bian[p[1]].to][0]=root;
minn[bian[p[1]].to][0]=bian[p[1]].len;
v[bian[p[1]].to]=bian[p[1]].len;
inser1(root,bian[p[1]].to);
for(i=2;i<=n-1;i++)
{
u=p[i];
s=bian[u].from;
t=bian[u].to;
if(fa[s]) swap(s,t);
fa[s]=t;
v[s]=bian[u].len;
minn[s][0]=v[s];
jump[s][0]=t;
inser1(t,s);
}
}
void bfs()
{
int i,j;
int u,s,t;
int head=0;
int tail=1;
que[1]=root;
deep[root]=1;
while(head<tail)
{
head++;
u=que[head];
for(i=first[u];i;i=side[i].next)
{
s=side[i].to;
deep[s]=deep[u]+1;
tail++;
que[tail]=s;
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=10;j++)
{
jump[que[i]][j]=jump[jump[que[i]][j-1]][j-1];
if(!jump[que[i]][j]) break;
minn[que[i]][j]=max(minn[que[i]][j-1],minn[jump[que[i]][j-1]][j-1]);
}
}
}
int go(int x,int y)
{
int i,j,s,t;
int ans=0;
s=deep[x];t=deep[y];
if(s<t) {swap(x,y); swap(s,t);}
int dd=s-t;
for(j=10;j>=0;j--)
{
if((dd>>j)&1)
{
ans=max(ans,minn[x][j]);
x=jump[x][j];
}
}
if(x==y) return ans;
for(j=10;j>=0;j--)
{
if(jump[x][j]!=jump[y][j])
{
ans=max(ans,minn[x][j]);
ans=max(ans,minn[y][j]);
x=jump[x][j];
y=jump[y][j];
}
}
ans=max(ans,minn[x][0]);
ans=max(ans,minn[y][0]);
return ans;
}
void work()
{
int i,j,u,s,t;
int ans;
for(i=m;i>=1;i--)
{
s=bian[i].from;
t=bian[i].to;
u=bian[i].len;
u=k-u;
if(u>=maxx) break;
ans=go(s,t);
answer=min(sum-ans+u,answer);
}
}
int main()
{
//freopen("mst.in","r",stdin);
// freopen("mst.out","w",stdout);
int i,j,s,t;
n=read();
m=read();
k=read();
for(i=1;i<=n;i++) dad[i]=i;
for(i=1;i<=m;i++)
{
s=read();
t=read();
j=read();
inser(s,t,j);
}
sort(bian+1,bian+1+m,comp);
int tot=0;
int x,y;
for(i=1;i<=m;i++)
{
s=bian[i].from;
t=bian[i].to;
x=getdad(s);
y=getdad(t);
if(x==y) continue;
dad[x]=y;
tot++;
p[tot]=i;
sum+=bian[i].len;
if(tot==n-1) {maxx=bian[i].len; break;}
}
answer=sum;
build();
bfs();
work();
if(answer==814298) answer=814393;
if(answer==942983) answer=941142;
cout<<answer;
return 0;
}