1. 程式人生 > 實用技巧 >判斷素數

判斷素數

題目描述:

Mr. W got a new graph with N vertices and N - 1 edges. It's a connected graph without cycles. Each edge should have an ugly value. To make the graph more beautiful, Mr. W hope you can help him modify it. You can delete or add one edge with an ugly value at a time and you can do it as many times as you want. But the following conditions should be satisfied at any time:
1. The graph is connected. 2. For each cycles in the graph, the XOR sum of all ugly values in the cycle is 0. Mr. W wants to know the minimum sum of ugly values of all edges in the graph.

輸入描述:

輸出描述:

示例:

輸入
6
0 1 1
1 2 4
1 3 3
0 4 5
0 5 2

  

輸出
7

做法:我們腦袋一拍,可以發現任意兩個點之間連邊的權值都是固定的。

由於可以得出:圖始終聯通,所以兩點間始終存在至少一條路徑,如果存在多條,那麼根據:

  • 環的異或和為0;
  • 兩點間的路徑的異或和應該相等,且始終是固定的。

所以可以給每個點一個權值,那麼兩點間的連邊權值就應該是兩端點權的異或。

接下來的問題就是異或最小生成樹。

字典樹 就TM煩。

接下來便是參考程式碼:

#include<bits/stdc++.h>
using namespace std;
int n,tot,cnt;
int head[100005],dp[100005],tree[30000010][2];
long long ans;
struct node
{
    int v;
    int w;
    int next;
}a[100005<<1];
void dfs(int
x,int h) { for (int i=head[x]; i!=-1; i=a[i].next) { int v=a[i].v; if(v==h) continue; dp[v]=dp[x]^a[i].w; dfs(v,x); } } void insert(int x) { int p=0; for (int i=29; i>=0; i--) { int now=x>>i&1; if(!tree[p][now]) { cnt++; tree[p][now]=cnt; tree[cnt][0]=0; tree[cnt][1]=0; } p=tree[p][now]; } } int ask(int x) { int p=0,ans=0; for (int i=29; i>=0; i--) { int now=x>>i&1; if(!tree[p][now]) now^=1; p=tree[p][now]; if(now) ans+=1<<i; } return ans; } void bfs(int x, int l, int r) { if(x<0) return ; int mid=l-1; for (int i=l; i<=r; i++) if(!(1<<x&dp[i])) mid=i; if(l<=mid) bfs(x-1,l,mid); if(mid<r) bfs(x-1,mid+1,r); if(mid<l || mid>=r) return ; cnt=0; tree[0][0]=0; tree[0][1]=0; for (int i=l; i<=mid; i++) insert(dp[i]); int minn=0x3f3f3f3f; for (int i=mid+1; i<=r; i++) minn=min(minn,dp[i]^ask(dp[i])); ans+=minn; } int main() { memset(head,-1,sizeof(head)); scanf("%d",&n); int x,y,z; for (int i=1,u,v,w; i<n; i++){ scanf("%d%d%d",&x,&y,&z); x++,y++; a[tot].v=y; a[tot].w=z; a[tot].next=head[x]; head[x]=tot++; a[tot].v=x; a[tot].w=z; a[tot].next=head[y]; head[y]=tot++; } dfs(1,0); sort(dp+1,dp+1+n); bfs(29,1,n); printf("%lld\n", ans); return 0; }//碼農教程請不要爬我程式碼
View Code