0+40+10+0
一言以蔽之 曰 “一上午白乾”
T1 一般圖最小匹配
首先,對答案有貢獻的點對一定在排序後的位於相鄰位置
所以排序後取出所有 \(a_{i+1}-a_{i}\)
但不能像Kruskal一樣每次取最小,因為其只需要考慮連通性,不涉及其它限制。
所以用dp或者可反悔貪心取最優解
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int a[50005];
int dp[5005][5005];
signed main()
{
freopen("match.in","r",stdin);
freopen("match.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
memset(dp,0x3f,sizeof(dp));
for(int i=0;i<=n;i++) dp[i][0]=0;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=min(i/2+1,m);j++)
{
dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+a[i]-a[i-1]);
}
}
cout<<dp[n][m];
}
T2 重定向
從前向後掃描
對於分別考慮 \(a_{i}\) 和 \(a_{i+1}\) 是否選到 0,共四種情況。
用set維護出每個為 0 的位置可以填下的數
另外, 對於 一種情況 \(a_{i}=0\) 並且存在\(j>i\)並且\(a_{j}\)小於其可選的最小至,此時直接刪除\(j\)
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> ma;
int a[500005];
bool f[500005];
set<int >stk,sty;
int n;
int main()
{
freopen("repeat.in","r",stdin);
freopen("repeat.out","w",stdout);
int T;
cin>>T;
while(T--)
{
cin>>n;
memset(f,0,sizeof(f));
stk.clear();
sty.clear();
ma.clear();
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]) f[a[i]]=1,ma[a[i]]=i;
}
for(int i=1;i<=n;i++)
{
if(!f[i]) stk.insert(i);
else sty.insert(i);
}
int wei=0;
for(int i=1;i<=n;i++)
{
if(a[i]) sty.erase(a[i]);
if(a[i]&&a[i+1])
{
if(a[i]>a[i+1])
{
stk.insert(a[i]);
wei=i;
break;
}
}
if(a[i+1]==0&&a[i])
{
int x=*stk.begin();
if(x<a[i])
{
stk.insert(a[i]);
wei=i;
break;
}
}
if(a[i]==0)
{
int x=*stk.begin();
int y=*sty.begin();
if(y<x)
{
a[i]=y;
sty.erase(y);
wei=ma[y];
//cout<<"__";
break;
}
else
{
a[i]=x;
stk.erase(x);
}
}
}
if(wei==0) wei=n;
for(int i=1;i<=n;i++)
{
if(wei==i) continue;
if(a[i]==0)
{
int x=*stk.begin();
//int y=*sty.begin();
a[i]=x;
stk.erase(x);
}
}
for(int i=1;i<=n;i++)
{
if(wei==i) continue;
//tot++;
cout<<a[i]<<' ';
}
cout<<'\n';
}
}
T3 斯坦納樹
對於當前點集,當且僅當其在原樹上形成的虛樹存在虛點時答案為 0;
將用邊權為0的邊相連的點 ,合併為一個大點,只要大點內有一個點存在,即表示該大點存在;
-
可正徐維護,依次加點,將已有點集按\(dfs\) 序排序 ,將新增節點填入,若其與左右兩個節點分別形成的lca都位於已有點集內,則無新增虛點
-
也可倒敘刪點,對要刪除點,若當前相連的邊數大於3,則設為虛點;若等於2,則刪除,並將與其相連的兩個點連邊,保持連通性;若等於1 直接刪除; 對於每次刪除要遞迴處理
點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
struct node{
int f,to,next,w;
}ee[600005],e[600005];
int head[300005],cnt1,cnt;
bool del[300005],xvd[300005];
int fa[300005],siz[300005],in[300005],p[300005];
bool ans[300005];
int n,xv;
void add(int f,int t,int w)
{
e[++cnt].to=t;
e[cnt].f=f;
e[cnt].w=w;
e[cnt].next=head[f];
head[f]=cnt;
}
int find(int x)
{
if(fa[x]!=x) fa[x]=find(fa[x]);
return fa[x];
}
void merge(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx==fy) return;
fa[fx]=fy;
siz[fy]+=siz[fx];
}
void delet(int x)
{
del[x]=1;
if(in[x]==2)
{
int num1=0,num2=0;
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(!del[y]&&num1==0) num1=y;
else if(!del[y]&&num1) num2=y;
}
add(num1,num2,1);
add(num2,num1,1);
in[num1]++;
in[num2]++;
}
for(int i=head[x];i;i=e[i].next)
{
int y=e[i].to;
if(!del[y])
{
in[y]--;
if(xvd[y]&&in[y]==2)
{
xvd[y]=0;
del[y]=1;
xv--;
delet(y);
}
}
}
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
fa[i]=i;
siz[i]=1;
}
for(int i=1;i<n;i++)
{
int x,y,w;
cin>>x>>y>>w;
if(w==0) merge(x,y);
else
{
ee[++cnt1].f=x;
ee[cnt1].to=y;
ee[cnt1].w=w;
}
}
for(int i=1;i<=cnt1;i++)
{
int lx=find(ee[i].f),ly=find(ee[i].to);
in[lx]++,in[ly]++;
add(lx,ly,e[i].w);
add(ly,lx,e[i].w);
}
for(int i=1;i<=n;i++) cin>>p[i];
for(int i=n;i>=1;i--)
{
ans[i]=(xv==0);
int lx=find(p[i]);
siz[lx]--;
if(siz[lx]) continue;
if(in[lx]>=3) xvd[lx]=1,xv++;
else
{
del[lx]=1;
delet(lx);
}
}
for(int i=1;i<=n;i++) cout<<ans[i];
}
T4
不會
網路流
感覺 P2754在暗示什麼 打了四遍都在儲存前,電腦當機了