题目:
题意:
给出一张有很多条边的图,可能是非连通图
求在保留部分边的情况下同时符合喜好总和大于
k
、
k、
k、频宽最小
分析:
我一开始想用逆推法,就是枚举
m
m
m个边,从
t
a
ta
ta开始建边,随后向两边拓展,用
d
f
s
dfs
dfs实现。当然,只有愉快的
45
45
45分
后来实在无望,就打了个暴力,忽然发现时间复杂度居然优秀的达到了
O
(
m
2
)
O(m^2)
O(m2)
暴力为枚举首边,然后不断往后加入其它边,直到喜好程度符合要求
代码:
#pragma GCC optimize(2)
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define LZX ILU
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
LL n=read(),m=read(),k=read();
struct node{
LL x,y,w;
}e[5005];
bool cmp(node x,node y) {return x.w<y.w;}
LL f[1005],like[1005];
LL find(LL i) {return f[i]==i?i:f[i]=find(f[i]);}
LL l,r,ans=99999999;
LL tf[1005][1005][2];
void mogui(LL c)
{
if(c>=k) {ans=min(ans,e[r-1].w-e[l+1].w);return;}
LL a=e[l].x,b=e[l].y;
if(l>0)
{
int co[1005];
tf[l][r][0]=1;
LL c1=0,c2=0;
for(LL i=1;i<=n;i++)
{
if(find(i)==find(a)) c1++;
if(find(i)==find(b)) c2++;
}
for(LL i=1;i<=n;i++) co[i]=f[i];
f[find(a)]=find(b);
l--;
while(l>0&&(tf[l][r][0]||find(e[l].x)==find(e[l].y))) l--;
mogui(c-like[c1]-like[c2]+like[c1+c2]);
l++;
for(LL i=1;i<=n;i++) f[i]=co[i];
}
a=e[r].x,b=e[r].y;
if(r<=m)
{
int co[1005];
tf[l][r][1]=1;
LL c1=0,c2=0;
for(LL i=1;i<=n;i++)
{
if(find(i)==find(a)) c1++;
if(find(i)==find(b)) c2++;
}
for(LL i=1;i<=n;i++) co[i]=f[i];
f[find(a)]=find(b);
r++;
while(r<=m&&(tf[l][r][1]||find(e[r].x)==find(e[r].y))) r++;
mogui(c-like[c1]-like[c2]+like[c1+c2]);
r--;
for(LL i=1;i<=n;i++) f[i]=co[i];
}
return;
}
int main()
{
for(LL i=1;i<=n;i++) like[i]=read();
for(LL i=1;i<=m;i++) e[i].x=read(),e[i].y=read(),e[i].w=read();
sort(e+1,e+1+m,cmp);
for(LL i=1;i<=m;i++)
{
memset(tf,0,sizeof(tf));
l=i-1,r=i+1;
for(LL j=1;j<=n;j++) f[j]=j;
f[e[i].x]=find(e[i].y);
mogui(like[2]+(n-2)*like[1]);
}
if(ans==99999999) printf("T_T");
else cout<<ans;
return 0;
}