标签:include dijkstra 模板 min last 生成 端点 防止 operator
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define maxm 500000
int father[maxm],n,m,cnt,ans;
struct edge
{
int x,y,z;
bool operator < (const edge &s) const
{
return z<s.z;
}
}a[maxm];
int getfather(int x)
{
if(father[x]==x)
return x;
father[x]=getfather(father[x]);
return father[x];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
father[i]=i;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
}
sort(a+1,a+m+1);
for(int i=1;i<=m;i++)
{
int fx,fy;
fx=getfather(a[i].x);
fy=getfather(a[i].y);
if(fx==fy) continue;
father[fx]=fy;
cnt++;
ans+=a[i].z;
}
if(cnt!=n-1)
puts("orz\n");
else printf("%d\n",ans);
return 0;
}
类似dijkstra
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int maxm=1e6+7;
int pre[maxm],last[200007],other[maxm],len[maxm];
int dis[200007];
bool vis[200007];
int n,m,l,cnt;
priority_queue<pair<int,int > >q;
ll ans;
void add(int x,int y,int z)
{
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
len[l]=z;
}
void prim()
{
memset(dis,63,sizeof(dis));
dis[1]=0;
q.push(make_pair(0,1));
while(q.size()&&cnt<n)
{
int d=q.top().first,u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
cnt++;
ans+=-d;
for(int p=last[u];p;p=pre[p])
{
int v=other[p];
if(dis[v]>len[p])
{
dis[v]=len[p];
q.push(make_pair(-dis[v],v));
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
prim();
printf("%lld\n",ans);
return 0;
}
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int maxm=1e5+7;
int n;
struct node
{
int x,y;
int l;
bool operator < (const node &s ) const
{
return l<s.l;
}
}a[maxm];
ll ans;
int cnt[maxm],f[maxm];
int find(int x){
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].l);
ans+=a[i].l;
}
for(int i=1;i<=n;i++)
f[i]=i,cnt[i]=1;//类似prim算法中的集合概念
sort(a+1,a+n);
for(int i=1;i<=n-1;i++)//从小往大枚举,保证最小生成树唯一
{
int fx=find(f[a[i].x]);
int fy=find(f[a[i].y]);
if(fx!=fy)
{
f[fx]=fy;
ans+=(ll)(cnt[fx]*cnt[fy]-1)*(ll)(a[i].l+1);
cnt[fy]+=cnt[fx];
}
}
printf("%lld\n",ans);
return 0;
}
for(int j=1;j<=19;j++)
{
for(int i=1;i<=n;i++)
{
jump[i][j]=jump[jump[i][j-1]][j-1];
maxx[i][j]=max(maxx[i][j-1],maxx[jump[i][j-1]][j-1]);
if(maxx[i][j-1]==maxx[jump[i][j-1]][j-1])
mini[i][j]=max(mini[i][j-1],mini[jump[i][j-1]][j-1]);
else if(maxx[i][j-1]<maxx[jump[i][j-1]][j-1])
mini[i][j]=max(maxx[i][j-1],mini[jump[i][j-1]][j-1]);
else
mini[i][j]=max(mini[i][j-1],maxx[jump[i][j-1]][j-1]);
}
}
int qmax(int x,int y,int z)
{
int ans=-1;
for(int j=0;j<=19;j++)
{
if((dep[x]-dep[y])&(1<<j))
{
if(maxx[x][j]!=z)
ans=max(maxx[x][j],ans);
else ans=max(mini[x][j],ans);
x=jump[x][j];
}
}
return ans;
}
for(int i=1;i<=m;i++)
{
if(!vis[i])
{
int x=a[i].x;
int y=a[i].y;
int d=a[i].l;
int xy=lca(x,y);
int l1=qmax(x,xy,d);
int l2=qmax(y,xy,d);
ans=min(ans,cnt-max(l1,l2)+d);
}
}
bool check(int mid)
{
tot=0;
for(int i=0;i<=n-1;i++)
f[i]=i;
for(int i=1;i<=m;i++)
{
if(!a[i].color)
a[i].l+=mid;
}
sort(a+1,a+m+1);
int num=0;
for(int i=1;i<=m;i++)
{
int fx=find(a[i].x);
int fy=find(a[i].y);
if(fx!=fy)
{
f[fx]=fy;
tot+=a[i].l;
num+=a[i].color^1;
}
}
for(int i=1;i<=m;i++)
{
if(!a[i].color)
a[i].l-=mid;
}
if(num<cnt) return 0;
else return 1;
}
int l=-100,r=100;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))
{
l=mid+1;
ans=tot-cnt*mid;
}
else r=mid-1;
}
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int maxm=2007;
const ll mo=31011;
struct node
{
int x,y;
int l;
bool operator < (const node &s) const
{
return l<s.l;
}
}a[maxm];
int n,m;
int f[maxm];
ll ans=1,res;
struct lt
{
int l,r,cnt;
}b[maxm];
int find(int x)//为了能够快速分开连通块,并查集中不能使用路径压缩
{
return f[x]==x ? x : find(f[x]);
}
void dfs(int x,int l,int sum)
{
if(l>b[x].r){
if(sum==b[x].cnt)
res++;
return;
}
int fx=find(a[l].x);
int fy=find(a[l].y);
if(fx!=fy)
{
f[fx]=fy;
dfs(x,l+1,sum+1);
f[fx]=fx;
}
dfs(x,l+1,sum);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].l);
}
for(int i=1;i<=n;i++)
f[i]=i;
sort(a+1,a+m+1);
int tot=0,num=0;
for(int i=1;i<=m;i++)
{
if(a[i].l!=a[i-1].l) b[++tot].l=i,b[tot-1].r=i-1;
int fx=find(a[i].x);
int fy=find(a[i].y);
if(fx!=fy)
{
f[fx]=fy;
num++;
b[tot].cnt++;
}
}
b[tot].r=m;//防止最后几个相等,r不赋值
if(num!=n-1)
{
printf("0\n");
return 0;
}
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=tot;i++)
{
res=0;
dfs(i,b[i].l,0);
ans=ans*res%mo;
for(int j=b[i].l;j<=b[i].r;j++)
{
int fx=find(a[j].x);
int fy=find(a[j].y);
if(fx!=fy)
f[fx]=fy;
}
}
printf("%lld\n",ans);
return 0;
}
/*1.不同的最小生成树中,每种权值的边出现的个数是确定的
2.不同的生成树中,某一种权值的边连接完成后,形成的联通块状态是一样的*/
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
const int maxm=1e6+7;
struct node
{
int x,y;
double l;
bool operator < (const node &s) const
{
return l<s.l;
}
}a[maxm];
int n,tot;
double ans,maxx[1007][21],cnt;
double w[1007];
double x[1007],y[1007],len[2007];
int f[1007],l;
bool vis[1007];
int pre[2007],last[1007],other[2007];
int jump[1007][21],dep[1007];
priority_queue<pair<double ,int> >q;
double dis1(int i,int j)
{
return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
int find(int x)
{
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
void add(int x,int y,double z)
{
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
len[l]=z;
}
void dfs(int x)
{
for(int p=last[x];p;p=pre[p])
{
int v=other[p];
if(v==jump[x][0]) continue;
jump[v][0]=x;
dep[v]=dep[x]+1;
maxx[v][0]=len[p];
dfs(v);
}
}
double lca(int x,int y)
{
double ans=0;
if(dep[x]<dep[y]) swap(x,y);
for(int j=0;j<=19;j++)
{
if((dep[x]-dep[y])&(1<<j))
ans=max(ans,maxx[x][j]),x=jump[x][j];
}
if(x==y) return ans;
for(int j=19;j>=0;j--)
{
if(jump[x][j]!=jump[y][j])
{
ans=max(ans,maxx[x][j]);
ans=max(ans,maxx[y][j]);
x=jump[x][j];
y=jump[y][j];
}
}
return max(ans,max(maxx[x][0],maxx[y][0]));
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf",x+i,y+i,w+i);
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
a[++tot].x=i;
a[tot].y=j;
a[tot].l=dis1(i,j);
}
}
for(int i=1;i<=n;i++)
f[i]=i;
sort(a+1,a+tot+1);
for(int i=1;i<=tot;i++)
{
int fx=find(a[i].x);
int fy=find(a[i].y);
if(fx!=fy)
{
f[fx]=fy;
cnt+=a[i].l;
add(a[i].x,a[i].y,a[i].l);
add(a[i].y,a[i].x,a[i].l);
}
}
dfs(1);
for(int j=1;j<=19;j++)
{
for(int i=1;i<=n;i++)
{
jump[i][j]=jump[jump[i][j-1]][j-1];
maxx[i][j]=max(maxx[i][j-1],maxx[jump[i][j-1]][j-1]);
}
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
double ans1=lca(i,j);
ans=max(ans,(w[i]+w[j])/(cnt-ans1));
}
printf("%.2lf\n",ans);
return 0;
}
标签:include dijkstra 模板 min last 生成 端点 防止 operator
原文地址:https://www.cnblogs.com/lihan123/p/11663494.html