数据分割
Accepts: 202
Submissions: 1332
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
题目链接:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=775&pid=1002
想打死这个题的出题人,题意就看了我十分钟,这可是中文。。
赛时并没有做出来,赛后听大佬说可以二分过,姿势好的话启发式合并也可以,二分的方法大佬讲了,我也听懂了,但是我觉得我实现不出来那么高级的代码,毕竟菜,我就实现了一下启发式合并,不容易,一个晚上,终于让我搞出来了。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int N=100010;
int nd[N],nex[N],lnk[N];
int f[N],x[N],y[N],d[N],ans[N],top,L,n,s,e,E;
vector<int>fail[N];
int Find(int x){
return x==f[x]?x:f[x]=Find(f[x]);
}
void add(int u,int v){
//printf("ad %d %d\n",u,v);
nd[++E]=v;
nex[E]=lnk[u];
lnk[u]=E;
}
bool dfs(int u,int fa,int y){
//printf("%d\n",u);
for (int i=0;i<(int)fail[u].size();i++){
//printf("-%d\n",fail[u][i]);
if (Find(fail[u][i])==y)
return 1;
}
//printf("%d\n",u);
for (int i=lnk[u];i;i=nex[i]){
if(nd[i]!=fa){
if(dfs(nd[i],u,y))
return 1;
}
}
return 0;
}
void work(int u){
ans[++top]=s;
for (int j=u;j>u-s;j--){
f[x[j]]=x[j];
f[y[j]]=y[j];
d[x[j]]=d[y[j]]=1;
lnk[x[j]]=0;
lnk[y[j]]=0;
fail[x[j]].clear();
fail[y[j]].clear();
}
//printf("asd");
s=E=0;
}
int main(){
scanf("%d",&L);
for (int i=1;i<=L;i++){
f[i]=i;
d[i]=1;
}
s=E=0;
for (int i=1;i<=L;i++){
s++;
scanf("%d%d%d",&x[i],&y[i],&e);
int fx=Find(x[i]),fy=Find(y[i]);
if(!e){
if(fx==fy)
work(i);
else{
fail[x[i]].push_back(y[i]);
fail[y[i]].push_back(x[i]);
}
}
else{
if(fx!=fy){
if(d[fx]>d[fy])
swap(fx,fy);
//printf("==%d %d\n",fx,fy);
int t=dfs(fx,-1,fy);
if(t)
work(i);
else{
f[fx]=fy;
d[fy]+=d[fx];
add(fy,fx);
}
}
}
}
printf("%d\n",top);
for (int i=1;i<=top;i++)
printf("%d\n",ans[i]);
return 0;
}