- P3366 【模板】最小生成树
- P4180 [BJWC2010]严格次小生成树
- P2872 [USACO07DEC]Building Roads S
- P1991 无线通讯网
- P1967 货车运输
- P4047 [JSOI2010]部落划分
- P1113 杂务
- P1983 车站分级
- P1038 神经网络
- P5960 【模板】差分约束算法
- P3275 [SCOI2011]糖果
- P2294 [HNOI2005]狡猾的商人
- P4926 [1007]倍杀测量者
- P5590 赛车游戏
1.P3366 【模板】最小生成树
kruskal
#include<bits/stdc++.h>
using namespace std;
int n,m,a[5005],ans,cnt;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v,w;
}e[200005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+m,cmp);
for(int i=1;i<=m;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans+=e[i].w;
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=1;i<=m;i++){
e[i].u=read();
e[i].v=read();
e[i].w=read();
}
krus();
cout<<ans;
return 0;
}
prim
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define R register int
using namespace std;
int k,n,m,cnt,sum,ai,bi,ci,head[5005],dis[5005],vis[5005];
struct Edge
{
int v,w,next;
}e[400005];
void add(int u,int v,int w)
{
e[++k].v=v;
e[k].w=w;
e[k].next=head[u];
head[u]=k;
}
typedef pair <int,int> pii;
priority_queue <pii,vector<pii>,greater<pii> > q;
void prim()
{
dis[1]=0;
q.push(make_pair(0,1));
while(!q.empty()&&cnt<n)
{
int d=q.top().first,u=q.top().second;
q.pop();
if(vis[u]) continue;
cnt++;
sum+=d;
vis[u]=1;
for(R i=head[u];i!=-1;i=e[i].next)
if(e[i].w<dis[e[i].v])
dis[e[i].v]=e[i].w,q.push(make_pair(dis[e[i].v],e[i].v));
}
}
int main()
{
memset(dis,127,sizeof(dis));
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(R i=1;i<=m;i++)
{
scanf("%d%d%d",&ai,&bi,&ci);
add(ai,bi,ci);
add(bi,ai,ci);
}
prim();
if (cnt==n)printf("%d",sum);
else printf("orz");
}
2.P4180 [BJWC2010]严格次小生成树
咕咕咕了
3.P2872 [USACO07DEC]Building Roads S
#include<bits/stdc++.h>
using namespace std;
int n,m,a[5005],cnt,bs=1,qq;
int dis[1005][1005];
double ans;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v;
double w;
}e[1000005];
struct node{
double x,y;
}pos[1000005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+bs,cmp);
for(int i=1;i<=bs;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans+=e[i].w;
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=1;i<=n;i++){
pos[i].x=read();
pos[i].y=read();
}
for(int i=1;i<=m;i++){
int l1,l2;
l1=read(),l2=read();
dis[l1][l2]=1;
dis[l2][l1]=1;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
e[bs].u=i;
e[bs].v=j;
e[bs].w=(double)sqrt((pos[i].x-pos[j].x)*(pos[i].x-pos[j].x)+(pos[i].y-pos[j].y)*(pos[i].y-pos[j].y));
if(dis[i][j]==1){
e[bs].w=0;
}
bs++;
}
}
krus();
printf("%.2f",ans);
return 0;
}
4.P1991 无线通讯网
#include<bits/stdc++.h>
using namespace std;
int n,m,a[5005],cnt,bs=1,qq;
int dis[1005][1005];
double ans;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v;
double w;
}e[1000005];
struct node{
double x,y;
}pos[1000005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+bs,cmp);
for(int i=1;i<=bs;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans=max(ans,e[i].w);
hb(u,v);
if(++cnt==n-m)break;
}
}
int main(){
m=read(),n=read();
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=1;i<=n;i++){
pos[i].x=read();
pos[i].y=read();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
e[bs].u=i;
e[bs].v=j;
e[bs].w=(double)sqrt((pos[i].x-pos[j].x)*(pos[i].x-pos[j].x)+(pos[i].y-pos[j].y)*(pos[i].y-pos[j].y));
bs++;
}
}
krus();
printf("%.2f",ans);
return 0;
}
5.P1967 货车运输
这题就跟前面几个水题不一样了
先用kruskal求最大生成树并建新树,再魔改一下lca(保存儿子到父亲路径的最小权值)
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e4+5,maxm=1e5+5;
int f[maxn];
int head[maxn],fa[maxn][22],cnt,dep[maxn],lg[maxm],w[maxn][22],head2[maxn];
int n,m,q;
struct edge{
int u,v,w,nex;
}e[maxm],e2[maxm];
inline void add(int u,int v,int w){
e[++cnt].v=v;
e[cnt].u=u;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
int cnt2;
inline void add2(int u,int v,int w){
e2[++cnt2].v=v;
e2[cnt2].u=u;
e2[cnt2].w=w;
e2[cnt2].nex=head2[u];
head2[u]=cnt2;
}
int find(int x){
if(x==f[x])return x;
return f[x]=find(f[x]);
}
void hb(int x,int y){
int fx=find(x);
int fy=find(y);
f[fx]=fy;
}
void dfs(int u,int fath){
fa[u][0]=fath;
dep[u]=dep[fath]+1;
for(int i=1;i<=lg[dep[u]];i++){
fa[u][i]=fa[fa[u][i-1]][i-1];
w[u][i]=min(w[u][i-1],w[fa[u][i-1]][i-1]);
}
for(int i=head2[u];i;i=e2[i].nex){
if(e2[i].v!=fath){
w[e2[i].v][0]=e2[i].w;
dfs(e2[i].v,u);
}
}
}
int lca(int x,int y){
if(find(x)!=find(y))return -1;
int ans=0x3f3f3f3f;
if(dep[x]<dep[y])swap(x,y);
while(dep[x]>dep[y]){
ans=min(ans,w[x][lg[dep[x]-dep[y]]-1]);
x=fa[x][lg[dep[x]-dep[y]]-1];
}
if(x==y)return ans;
for(int k=lg[dep[x]]-1;k>=0;k--){
if(fa[x][k]!=fa[y][k]){
ans=min(ans,min(w[x][k],w[y][k]));
x=fa[x][k];
y=fa[y][k];
}
}
return min(ans,min(w[x][0],w[y][0]));
}
bool cmp(edge x,edge y){
return x.w>y.w;
}
void krus(){
sort(e+1,e+1+m,cmp);
int ans=0;
for(int i=1;i<=m;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
hb(u,v);
add2(u,v,e[i].w);
add2(v,u,e[i].w);
if(++ans==n)break;
}
}
int main(){
cin>>n>>m;
int u,v,ww;
for(int i=1;i<=n;i++){
f[i]=i;
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&ww);
add(u,v,ww);
}
for(int i=1;i<=n;i++){//预先算出log_2(i)+1的值,用的时候直接调用就可以了
lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
krus();
dfs(1,0);
cin>>q;
for(int i=1;i<=q;i++){
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return 0;
}
6.P4047 [JSOI2010]部落划分
#include<bits/stdc++.h>
using namespace std;
int n,m,a[5005],cnt,bs=1,qq;
int dis[1005][1005];
double ans;
double l,r;
vector<double>g;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v;
double w;
}e[1000005];
struct node{
double x,y;
}pos[1000005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp1(edge a,edge b){
return a.w<b.w;
}
bool cmp2(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+bs,cmp2);
for(int i=1;i<=bs;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
hb(u,v);
if(++cnt==n-m+1){
ans=e[i].w;
break;
}
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=1;i<=n;i++){
pos[i].x=read();
pos[i].y=read();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
e[bs].u=i;
e[bs].v=j;
e[bs].w=(double)sqrt((pos[i].x-pos[j].x)*(pos[i].x-pos[j].x)+(pos[i].y-pos[j].y)*(pos[i].y-pos[j].y));
bs++;
}
}
sort(e+1,e+1+bs,cmp1);
for(int i=1;i<=n-m;i++){
dis[e[i].u][e[i].v]=0;
e[i].w=0;
}
krus();
printf("%.2f",ans);
return 0;
}
7.P1113 杂务
小裸拓扑排序,之前学的时候拿这题写过题解,拓扑排序过程中记录更新最大时间即可
#include<bits/stdc++.h>
using namespace std;
vector<int>a[10005];
int t[10005];
int s[10005];
int n,m,c,k;
int ru[10005],chu[10005];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int x,y,z;
scanf("%d %d",&x,&t[i]);
s[i]=t[i];
while(1){
cin>>z;
a[x].push_back(z);
ru[z]++;
if(z==0)break;
}
}
queue<int>q;
for(int i=1;i<=n;i++){
if(!ru[i]){
q.push(i);
}
}
while(!q.empty()){
int v=q.front();
q.pop();
for(int i=0;i<a[v].size();i++){
ru[a[v][i]]--;
s[a[v][i]]=max(s[a[v][i]],s[v]+t[a[v][i]]);
if(ru[a[v][i]]==0){
q.push(a[v][i]);
}
}
}
for(int i=1;i<=n;i++){
c=max(c,s[i]);
}
cout<<c;
return 0;
}
8.P1983 车站分级
对于一趟车,起始中每一个不停的站点的等级都是低于路途中停下来的站点,记录下来,读入完毕之后进行拓扑排序,记录最大等级即可
#include<bits/stdc++.h>
using namespace std;
vector<int>a[1005],st[1005];
bool lian[1005][1005];
int ru[1005];
int n,m,c,ans,s;
int t[1005],den[1005];
int main(){
cin>>n>>m;
// memset(lian,false,sizeof(lian));
for(int i=1;i<=m;i++){
memset(t,0,sizeof(t));
int x,y;
scanf("%d",&x);
for(int j=1;j<=x;j++){
scanf("%d",&y);
t[y]++;
st[i].push_back(y);
}
for(int j=0;j<st[i].size();j++){
for(int k=st[i][0];k<=st[i][x-1];k++){
if(t[k]==0&&lian[k][st[i][j]]==false){
a[k].push_back(st[i][j]);
ru[st[i][j]]++;
lian[k][st[i][j]]=true;
}
}
}
}
queue<int>q;
for(int i=1;i<=n;i++){
if(ru[i]==0){
q.push(i);
den[i]=1;
}
}
while(q.size()!=0){
int now=q.front();
q.pop();
for(int i=0;i<a[now].size();i++){
ru[a[now][i]]--;
if(ru[a[now][i]]==0){
q.push(a[now][i]);
den[a[now][i]]=den[now]+1;
}
}
}
for(int i=1;i<=n;i++){
ans=max(ans,den[i]);
}
cout<<ans;
return 0;
}
9.P1038 神经网络
题意搁这逼逼赖赖,其实就是裸拓扑排序
#include<bits/stdc++.h>
using namespace std;
const int maxn=205,maxm=20005;
int n,p,c[maxn],head[maxn],cnt,vis[maxn],chu[maxn];
struct edge{
int v,w,nex;
}e[maxm];
inline void add(int u,int v,int w){
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
int main(){
cin>>n>>p;
int x,y;
queue<int>q;
for(int i=1;i<=n;i++){
cin>>c[i]>>y;
if(c[i]){
q.push(i);
vis[i]=1;
}
else{
c[i]-=y;
}
}
int u,v,w;
for(int i=1;i<=p;i++){
cin>>u>>v>>w;
add(u,v,w);
chu[u]=1;
}
while(!q.empty()){
int u=q.front();
q.pop();
if(c[u]<=0)continue;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].v;
c[v]+=e[i].w*c[u];
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
int f=0;
for(int i=1;i<=n;i++){
if(chu[i]==0&&c[i]>0){
printf("%d %d\n",i,c[i]);
f=1;
}
}
if(f==0)puts("NULL");
return 0;
}
10.P5960 【模板】差分约束算法
套公式,建源点
#include<bits/stdc++.h>
using namespace std;
const int maxm=10005;
struct edge{
int v,w,nex;
}e[maxm];
int head[maxm],dis[maxm],inq[maxm],cnt,n,m,cs[maxm];
inline void add(int u,int v,int w){
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
bool spfa(int s){
queue<int>q;
memset(dis,0x3f,sizeof dis);
dis[s]=0;
inq[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
inq[u]=0;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!inq[v]){
q.push(v);
cs[v]++;
if(cs[v]==n)return true;
}
}
}
}
return false;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
add(0,i,0);
}
int u,v,w;
for(int i=1;i<=m;i++){
cin>>u>>v>>w;//不等式: u-v<=w
add(v,u,w);
}
if(spfa(0))puts("NO");
else{
for(int i=1;i<=n;i++){
cout<<dis[i]<<" ";
}
}
return 0;
}
11.P3275 [SCOI2011]糖果
对五种情况进行套公式即可
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=4e5+5;
struct edge{
int v,w,nex;
}e[maxm];
int head[maxm],dis[maxm],inq[maxm],cnt,n,m,cs[maxm];
inline void add(int u,int v,int w){
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
bool spfa(int s){
queue<int>q;
memset(dis,-0x3f,sizeof dis);
dis[s]=0;
inq[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
inq[u]=0;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].v;
if(dis[v]<dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!inq[v]){
q.push(v);
cs[v]++;
if(cs[v]==n)return true;
}
}
}
}
return false;
}
signed main(){
cin>>n>>m;
for(int i=n;i>=1;i--){
add(0,i,1);
}
int x,a,b;
int fafa=0;
for(int i=1;i<=m;i++){
scanf("%lld%lld%lld",&x,&a,&b);
if(x==1){
add(b,a,0);
add(a,b,0);
}
else if(x==2){
add(a,b,1);
}
else if(x==4){
add(b,a,1);
}
else if(x==3){
add(b,a,0);
}
else if(x==5){
add(a,b,0);
}
if(x%2==0&&a==b){
fafa=1;
}
}
if(fafa==1){
puts("-1");
return 0;
}
long long ans=0;
int tt=-1e18+5;
if(spfa(0)){
puts("-1");
return 0;
}
else{
for(int i=1;i<=n;i++){
ans+=dis[i];
}
}
cout<<ans;
return 0;
}
12.P2294 [HNOI2005]狡猾的商人
有环即为false,不要建源点
#include<bits/stdc++.h>
using namespace std;
const int maxm=4e5+5;
struct edge{
int v,w,nex;
}e[maxm];
int head[maxm],dis[maxm],inq[maxm],cnt,n,m,cs[maxm];
inline void add(int u,int v,int w){
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
bool spfa(int s){
queue<int>q;
memset(dis,0x3f,sizeof dis);
memset(inq,0,sizeof(inq));
memset(cs,0,sizeof(cs));
dis[s]=0;
inq[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
inq[u]=0;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!inq[v]){
q.push(v);
cs[v]++;
if(cs[v]==n)return true;
}
}
}
}
return false;
}
inline void init(){
memset(head,0,sizeof head);
cnt=0;
}
signed main(){
int tt;
cin>>tt;
int s,t,w;
while(tt--){
cin>>n>>m;
init();
for(int i=1;i<=m;i++){
cin>>s>>t>>w;
add(s-1,t,w);
add(t,s-1,-w);
}
if(!spfa(0))printf("true\n");
else printf("false\n");
}
return 0;
}
13.P4926 [1007]倍杀测量者
咕咕咕
14.P5590 赛车游戏
咕咕咕