Za
Kruskal
#include
using namespace std;
#define ll long long
const int N=2e5+5,M=5e5+5,inf=0x3f3f3f3f;
int n,m;
ll ans=0;
templatevoid rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
struct edge{
int u,v,w;
bool operator<(const edge&X)const{return w
prim
#include
using namespace std;
#define ll long long
typedef pairpii;
priority_queue,greater >q;
const int N=2e5+5,M=5e5+5,inf=0x3f3f3f3f;
int n,m;
ll ans=0;
templatevoid rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],tot=0;
struct edge{int v,w,nxt;}e[M<<1];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}
int dis[N],vis[N];
void prim(){
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
q.push(make_pair(dis[1]=0,1));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u]) continue;
ans+=dis[u],vis[u]=1;
for(int i=head[u],v,w;i;i=e[i].nxt)
if(!vis[v=e[i].v]&&dis[v]>(w=e[i].w))
dis[v]=w,q.push(make_pair(dis[v],v));
}
}
int main(){
rd(n),rd(m);
for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),add(u,v,w),add(v,u,w);
prim();
printf("%lld",ans);
return 0;
}
走廊泼水节
将给定的树增加若干条边使其变为完全图 而该树仍未该图中最小生成树
因为要保证该树仍未图中最小生成树 所以连的边得为其最小边权+1
集合\(S_x\)与\(S_y\)之间一共会增加\(|S_x|*|S_Y|-1\)条边
#include
using namespace std;
#define ll long long
typedef pairpii;
priority_queue,greater >q;
const int N=6000+5,M=5e5+5,inf=0x3f3f3f3f;
int n,m,f[N],sz[N];
ll ans;
templatevoid rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
struct edge{
int u,v,w;
bool operator<(const edge&X)const{return w
POJ1639 Picnic Planning
给定一张\(N\)个点\(M\)条边的无向图 求出其一棵最小生成树满足1号节点的读书不超过给定整数\(S\)
CF891C Envy
CF891C luogu
==是看的yyb的
- 对于任意权值的边,所有最小生成树中这个权值的边的数量是一定的
- 对于任意正确加边方案,加完小于某权值的所有边后图的连通性是一样的
将所有权值相同的边一起考虑 由2可得它们连出来的结果是固定的
将连边改为脸连通块
预处理时将每个小于\(w_i\)的边先加入 再加入边权为\(w_i\)的边 若形成环 则这组询问失败
在每次寻问候要将这次询问所构成的修改还原==
#include
using namespace std;
#define ll long long
typedef pairpii;
const int N=5e5+5,M=5e5+5,inf=0x3f3f3f3f;
int n,m,s,tt,f[N];
templatevoid rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
struct edge{
int u,v,w,id;
bool operator<(const edge&X)const{return w
[JLOI2011]飞行路线
分层最短路模板?注意要用dijkstra
==有组数据是m
四倍经验==
#include
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define ll long long
const int N=10000+10,M=50000+10,inf=0x3f3f3f3f;
int n,m,K,s,t;
template void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],tot=0;
struct edge{int v,w,nxt;}e[M<<1];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}
int dis[N][12];bool vis[N][12];
struct node{
int dis,id,us;
bool operator>(const node&X)const{return dis>X.dis;}
};
priority_queue,greater >q;
void dij(){
memset(dis,inf,sizeof(dis));
memset(vis,0,sizeof(vis));
q.push((node){0,s,0}),dis[s][0]=0;
while(!q.empty()){
node nw=q.top();q.pop();
int u=nw.id,us=nw.us;
if(vis[u][us]) continue;
vis[u][us]=1;
for(int i=head[u],v,w;i;i=e[i].nxt){
if(dis[v=e[i].v][us]>dis[u][us]+(w=e[i].w))//不用
q.push((node){dis[v][us]=dis[u][us]+(w=e[i].w),v,us});
if(usdis[u][us])
if(!vis[v][us+1]) q.push((node){dis[v][us+1]=dis[u][us],v,us+1});
}
}
}
int main(){
freopen("in.txt","r",stdin);
rd(n),rd(m),rd(K),rd(s),rd(t),++s,++t;
for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),add(++u,++v,w),add(v,u,w);
spfa();
if(dis[t][K]==inf) return puts("-1"),0;
int ans=inf;
for(int i=0;i<=K;++i) ans=Min(ans,dis[t][i]);
printf("%d",ans);
return 0;
}
[USACO14OPEN]GPS的决斗Dueling GPS's
luoguP3106 bzoj3538
hin水? 分别跑三次dijkstra
#include
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define ll long long
const int N=10000+10,M=50000+10,inf=0x3f3f3f3f;
typedef pairpii;
int n,m,K,s,t,w2[M];
template void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
int head[N],tot=0;
struct edge{int v,w,nxt;}e[M];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}
int dis[N],nw[M],tg[M];bool vis[N];
priority_queue,greater >q;
void dij(){
memset(nw,0,sizeof(nw));
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
dis[s]=0,q.push(make_pair(0,s));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u],v,w;i;i=e[i].nxt)
if(dis[v=e[i].v]>dis[u]+(w=e[i].w)){
++tg[nw[v]],nw[v]=i,--tg[i];
q.push(make_pair(dis[v]=dis[u]+w,v));
}
}
}
int main(){
freopen("in.txt","r",stdin);
rd(n),rd(m),s=n;
for(int i=1,u,v,w1;i<=m;++i) rd(u),rd(v),rd(w1),rd(w2[i]),add(v,u,w1),tg[i]=2;
dij();
for(int i=1;i<=m;++i) e[i].w=w2[i];
dij();
for(int i=1;i<=m;++i) e[i].w=tg[i];
dij();
printf("%d",dis[1]);
return 0;
}
树网的核
枚举\(O(n^3)\)
两次bfs求出任一直径 枚举距离不超过\(s\)的两个点\(p,q\) 然后从核上每个结点出发去求距离 取其中最小值
枚举+贪心\(O(n^2)\)
可以知道\(p,q\)两个点距离越远越好 所以只需在直径上枚举\(p\)点然后直接算出距离其\(s\)的\(q\)点
二分\(O(n\ log\ SUM)\)
可发现答案具有单调性 二分偏心距的可能的最小值 check是否存在这样一个核
单调队列\(O(n)\)
咕==
luoguP2245 星际导航
复习了一遍货车运输?
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
#define rg register
const int N=100000+5,M=500000+5,inf=0x3f3f3f3f,P=19650827;
int n,m,q;
int dep[N],p[N][25],w[N][25];
template void rd(t &x){
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
}
struct edg{int u,v,w;}E[M];
bool cmp(edg a,edg b){return a.wdep[b]) swap(a,b);
for(int i=20;i>=0;--i){
if(dep[p[b][i]]=0;--i){
if(p[a][i]==p[b][i]) continue;
ans=max(ans,max(w[a][i],w[b][i]));
a=p[a][i],b=p[b][i];
}
ans=max(ans,max(w[a][0],w[b][0]));
return ans;
}
int main(){
freopen("in.txt","r",stdin);
rd(n),rd(m);
for(int i=1,u,v,w;i<=m;++i) rd(u),rd(v),rd(w),E[i]=(edg){u,v,w};
sort(E+1,E+m+1,cmp);
kruskal(),build();
rd(q);
for(int i=1,u,v;i<=q;++i){
rd(u),rd(v);
if(find(u)!=find(v)) puts("impossible");
else printf("%d\n",LCA(u,v));
}
return 0;
}