洛谷传送门
BZOJ传送门
LOJ传送门
解析:
显然就是求树上有多少不同的边权,树都不用建出来,直接用一个set统计一下就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
using std::cout;
using std::cerr;
cs int N=852;
int n,m;
std::set<int> s;
namespace NetWork{
struct edge{
int to,cap,rev,w;
edge(cs int &_to,cs int &_w,cs int &_rev):to(_to),w(_w),rev(_rev){}
};
std::vector<edge> G[N];
typedef std::vector<edge>::iterator iter;
iter cur[N];
inline void addedge(int u,int v,int val){
G[u].push_back(edge(v,val,G[v].size()));
G[v].push_back(edge(u,val,G[u].size()-1));
}
int lev[N],gap[N];
int S,T;
inline void BFS(){
memset(lev+1,0,sizeof(int)*n);
memset(gap,0,sizeof(int)*(n+2));
lev[T]=gap[1]=1;
std::queue<int> q;q.push(T);
while(!q.empty()){
int u=q.front();q.pop();
for(iter re e=G[u].begin();e!=G[u].end();++e)
if(!lev[e->to])q.push(e->to),++gap[lev[e->to]=lev[u]+1];
}
}
inline int dfs(int u,cs int &flow){
if(u==T)return flow;
int ans=0;
for(iter &e=cur[u];e!=G[u].end();++e)
if(e->cap&&lev[e->to]+1==lev[u]){
int delta=dfs(e->to,std::min(e->cap,flow-ans));
if(delta){
ans+=delta;
e->cap-=delta;
G[e->to][e->rev].cap+=delta;
if(ans==flow)return ans;
}
}
if(--gap[lev[u]]==0)lev[S]=n+1;
++gap[++lev[u]];
return ans;
}
inline int ISAP(cs int s,cs int t){
S=s,T=t;
for(int re i=1;i<=n;++i)
for(iter re e=G[i].begin();e!=G[i].end();++e)e->cap=e->w;
int mxflow=0;BFS();
while(lev[S]<=n){
for(int re i=1;i<=n;++i)cur[i]=G[i].begin();
mxflow+=dfs(s,0x3f3f3f3f);
}
return mxflow;
}
int vis[N],idx;
inline void dfs(int u){
vis[u]=idx;
for(iter re e=G[u].begin();e!=G[u].end();++e)
if(e->cap&&vis[e->to]!=idx)dfs(e->to);
}
int p[N],tmp[N];
inline void build(int l,int r){
if(l>=r)return ;
int s=p[l],t=p[l+1],cut=ISAP(s,t);
::s.insert(cut);
++idx;dfs(s);int L=l,R=r;
for(int re i=l;i<=r;++i)tmp[vis[p[i]]==idx?L++:R--]=p[i];
for(int re i=l;i<=r;++i)p[i]=tmp[i];
build(l,L-1),build(R+1,r);
}
inline void init(){
for(int re i=1;i<=n;++i)p[i]=i;
build(1,n);
}
}
signed main(){
n=getint(),m=getint();
for(int re i=1,u,v,val;i<=m;++i){
u=getint(),v=getint(),val=getint();
NetWork::addedge(u,v,val);
}
NetWork::init();
cout<<s.size()<<"\n";
return 0;
}

本文介绍了一种高效的算法来解决树上不同边权数量的问题。通过使用集合数据结构进行边权值的统计,避免了构建整棵树的过程,实现了快速求解。
523

被折叠的 条评论
为什么被折叠?



