T1一般图最小匹配
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5000+107;
int n,m,a[N];
int read()
{
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return f*s;
}
int f[N][N];
signed main()
{
freopen("match.in","r",stdin);
freopen("match.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
sort(a+1,a+1+n);
memset(f,0x3f,sizeof f);
f[0][0]=0;
f[1][0]=0;
for(int i=2;i<=n;i++)
{
f[i][0]=f[i-1][0];
for(int j=1;j<=m;j++)
{
f[i][j]=min(f[i-1][j],f[i-2][j-1]+a[i]-a[i-1]);
}
}
printf("%lld",f[n][m]);
}
T2重定向
无任何算法,我们直接考虑即可,那我们先想,自然是把所有的空位按递增序列填就行,我们用一个 \(set\) 来维护,那我们考虑什么用删除,这删除肯定是越早用越好。
如果我们遍历到的数是 \(0\) ,我们直接比较它要被填上的数和它后面最小的数,如果后面的数更优,直接删掉,在加到 \(set\) 里面,否则直接为它附上值。
如果遍历到的数非零且后一个数也非零,我们直接比较判断即可。如果后一个数为 \(0\) ,我们比较那一位要填上的数和现在的数即可。
额,好像就没了……
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+107;
int n,a[N];
int nxt[N];
bool vis[N];
set<int>s;
int read()
{
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return f*s;
}
int main()
{
freopen("repeat.in","r",stdin);
freopen("repeat.out","w",stdout);
int T=read();
while(T--)
{
s.clear();
memset(vis,0,sizeof vis);
memset(nxt,0x3f,sizeof nxt);
n=read();
for(int i=1;i<=n;i++) a[i]=read(),vis[a[i]]=1;
for(int i=1;i<=n;i++) if(!vis[i]) s.insert(i);
for(int i=n;i>=1;i--)
{
if(a[i+1]!=0) nxt[i]=min(nxt[i+1],a[i+1]);
else nxt[i]=nxt[i+1];
}
int cnt=1,pos=0;
for(int i=1;i<=n;i++)
{
if(a[i]==0)
{
if(*s.begin()>nxt[i])
{
pos=nxt[i];
s.insert(nxt[i]);
cnt--;
break;
}
}
else
{
if(a[i+1]==0&&*s.begin()<a[i])
{
pos=a[i],cnt--;
s.insert(a[i]);
break;
}
if(a[i+1]!=0&&a[i+1]<a[i])
{
pos=a[i],cnt--;
s.insert(a[i]);
break;
}
}
if(a[i]==0) a[i]=*s.begin(),s.erase(*s.begin());
}
if(cnt) pos=a[n];
for(int i=1;i<=n;i++)
{
if(a[i]==pos) continue;
if(a[i]!=0) printf("%d ",a[i]);
if(a[i]==0)
{
printf("%d ",*s.begin());
s.erase(*s.begin());
}
}
printf("\n");
}
}
T3 斯坦纳树
我们每经过一条路径,我们就把每个点标记上,在拓展一个新点的时候,我们直接让它往它和上一个节点的 \(lca\) 上跳,跳到第一个被标记且之前没有拓展过,我们把它存到 \(set\) 里,每拓展一个新数,如果 \(set\) 里面有对应的值,把它删掉,至于边权为 \(0\) ,我们直接合并成一个点。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+107;
int n,p[N];
int bel[N];
int read()
{
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return f*s;
}
int h[N<<1],to[N<<1],nxt[N<<1],tot;
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=h[x];
h[x]=tot;
}
int f[N][40],dep[N];
void dfs(int u,int fa)
{
f[u][0]=fa,dep[u]=dep[fa]+1;
for(int i=1;i<=30;i++) f[u][i]=f[f[u][i-1]][i-1];
for(int i=h[u];i;i=nxt[i])
{
int v=to[i];
if(v==fa) continue;
dfs(v,u);
}
}
int get_lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=30;i>=0;i--)
{
if(dep[f[x][i]]>=dep[y])
{
x=f[x][i];
}
}
if(x==y) return x;
for(int i=30;i>=0;i--)
{
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][0];
}
set<int> s;
bool vis[N];
int flag[N];
void label(int x,int lca)
{
if(vis[x]) return ;
if(x==lca) return ;
while(1)
{
vis[x]=1;
x=f[x][0];
if(x==lca)
{
if(vis[x]&&!flag[x]) s.insert(x);
else vis[x]=1;
break;
}
if(vis[x])
{
if(!flag[x]) s.insert(x);
break;
}
}
}
struct lmy
{
int x,y,w;
}e[N];
bool comp(lmy a,lmy b)
{
if(a.w==b.w) return a.x<b.x;
return a.w<b.w;
}
int find(int x)
{
return bel[x]==x?x:bel[x]=find(bel[x]);
}
signed main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n=read();
for(int i=1;i<=n*2;i++) bel[i]=i;
for(int i=1;i<n;i++)
{
int x=read(),y=read(),w=read();
if(y<x) swap(x,y);
e[i]={x,y,w};
}
sort(e+1,e+1+n-1,comp);
for(int i=1;i<n;i++)
{
if(e[i].w==0)
{
int x=e[i].x,y=e[i].y;
if(bel[x]==x&&bel[y]==y) bel[x]=n+i,bel[y]=n+i;
else if(bel[x]!=x) bel[find(bel[y])]=find(bel[x]);
else if(bel[y]!=y) bel[find(bel[x])]=find(bel[y]);
}
else break;
}
for(int i=1;i<=n*2;i++) bel[i]=find(bel[i]);
for(int i=1;i<n;i++)
{
if(e[i].w==0) continue;
add(bel[e[i].x],bel[e[i].y]);
add(bel[e[i].y],bel[e[i].x]);
}
for(int i=1;i<=n;i++) p[i]=read();
dfs(bel[p[1]],bel[p[1]]);
flag[bel[p[1]]]=1;
printf("1");
for(int i=2;i<=n;i++)
{
s.erase(bel[p[i]]);
int lca=get_lca(bel[p[i]],bel[p[i-1]]);
flag[bel[p[i]]]=1;
if(i==2) label(bel[p[i-1]],lca);
label(bel[p[i]],lca);
if(!s.empty()) printf("0");
else printf("1");
}
}