Description
An undirected graph with mm edges of nn points and at most two paths between any two points is given. flow(s,t)flow(s,t) is used to represent the maximum flow between s, ts and t points. The maximum flow between 1 (< s < T < ns t flow(s,t) 1 (< s < T < ns t flow(s,t) is obtained.
Input
The first line, an integer TT, denotes the number of use cases. Each set of use cases first inputs two integers n,mn,m to denote the number of points and edges. The last mm line inputs three integers u,v,wu,v,w to denote the number of u, vu and V with a flow of w between them.
(1≤T≤100,1≤n≤105,n−1≤m≤32(n−1),0≤w≤109)(1≤T≤100,1≤n≤105,n−1≤m≤32(n−1),0≤w≤109)
Output
Output result
Sample Input
2
3 3
1 2 5
2 3 6
3 1 5
5 6
1 2 5
2 3 6
3 1 5
3 4 6
4 5 5
5 3 6
Sample Output
27
116
Solution
Since there are at most two paths before two points, it is obvious that each side belongs to at most one ring (otherwise there are at least four paths between points on two rings). The maximum flow between two points is equal to the minimum cut. If there is only one path between two points, then the minimum edge weight on this path will be cut off. If there are two paths between two points, then there are two cases, one is still broken. One edge with minimum edge weight makes two points unreachable, the other is to cut off two edges of the ring to make two points unreachable. At the same time, it is noted that if two edges of the ring are broken, then one of them must be the minimum edge weight of the ring, and the other one needs to be selected according to the reachability of two points. Then we delete the edge with minimum edge weight on each ring and add its edge weight to all the remaining edges of the ring. In edge weight, if the graph is transformed into a tree, the minimum cut between two points on the tree is equivalent to the minimum cut between the original graph. To find the minimum cut between two points on the tree, just like Kruskal Kruskal, adding edges from large to small according to the edge weight, and using and searching set to maintain connected components. The edge weight of the current added edge u vu v must be the minimum cut from the set point where u is located to the set point where vv is located. As a result, the sum of exclusive or exclusive numbers and minimal cuts should be accumulated, so the number of jj bits of binary system should be maintained in each link component. The state of two point sets at jj bit of edge weight should be judged according to the value of jj bit of edge weight each time. It is noted that the result will explode long and long unsigned long unsigned long
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef unsigned long long ull;
#define maxn 100005
struct Edge
{
int u,v,w,flag,next;
}edge[3*maxn];
int tot,head[maxn];
void add(int u,int v,int w)
{
edge[tot].u=u,edge[tot].v=v,edge[tot].w=w,edge[tot].flag=0;
edge[tot].next=head[u],head[u]=tot++;
}
int T,n,m,vis[maxn],pre[maxn];
vector<int>s,e;
void dfs(int u,int id)
{
vis[u]=1;
for(int i=head[u];~i;i=edge[i].next)
{
if(edge[i].flag)continue;
edge[i].flag=edge[i^1].flag=1;
int v=edge[i].v,w=edge[i].w;
s.push_back(i);
if(vis[v])
{
int mn=w;
for(int i=s.size()-1;i>=0;i--)
{
mn=min(mn,edge[s[i]].w);
edge[s[i]].flag=2;//Ring edge
if(edge[s[i]].u==v)break;
}
int flag=0;
while(1)
{
int temp=s.back();
s.pop_back();
if(!flag&&edge[temp].w==mn)flag=1;
else
{
edge[temp].w+=mn;
e.push_back(temp);
}
if(edge[temp].u==v)break;
}
continue;
}
dfs(v,i);
}
if(id!=-1&&edge[id].flag!=2)
{
e.push_back(s.back());
s.pop_back();
}
}
bool cmp(int x,int y)
{
return edge[x].w>edge[y].w;
}
int fa[maxn],num[maxn][31],Size[maxn];
int find(int x)
{
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
tot=0;
memset(head,-1,sizeof(head));
while(m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
}
e.clear();
memset(vis,0,sizeof(vis));
dfs(1,-1);
sort(e.begin(),e.end(),cmp);
for(int i=1;i<=n;i++)
{
fa[i]=i;
Size[i]=1;
for(int j=0;j<=30;j++)
if((i>>j)&1)num[i][j]=1;
else num[i][j]=0;
}
ull ans=0;
for(int i=0;i<e.size();i++)
{
int u=edge[e[i]].u,v=edge[e[i]].v,w=edge[e[i]].w;
u=find(u),v=find(v);
for(int j=0;j<=30;j++)
{
ull res=0;
if((w>>j)&1)
{
res+=(ull)num[u][j]*num[v][j];
res+=(ull)(Size[u]-num[u][j])*(Size[v]-num[v][j]);
}
else
{
res+=(ull)num[u][j]*(Size[v]-num[v][j]);
res+=(ull)(Size[u]-num[u][j])*num[v][j];
}
ans+=(1ull<<j)*res;
}
for(int j=0;j<=30;j++)num[v][j]+=num[u][j];
fa[u]=v,Size[v]+=Size[u];
}
printf("%llu\n",ans);
}
return 0;
}