1. 程式人生 > >HDU 6166 二進制劃分集合

HDU 6166 二進制劃分集合

memset push make bsp string void add 一個 gin

首先這個題化成兩個集合還是很容易的想到的,但是不知道怎麽用二進制表示,感覺這個題的腦洞還是很大的。

為什麽可以用二進制表示化成集合可以包含所有的點對,因為要是兩個數不同的話肯定會有一個二進制的位數不同

所以就包含了所有的點對。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int N=5e5;
struct node
{
    int u,v;
    long long w;
}s[N];
int node[N],nxt[N],head[N]; int n,m,tot,begins,vis[N]; long long d[N],data[N]; void add(int x,int y,long long z) { node[++tot]=y;nxt[tot]=head[x];head[x]=tot;data[tot]=z; } void inist() { //memset(vis,0,sizeof(vis)); tot=0; memset(node,0,sizeof(node)); memset(head,0,sizeof(head)); memset(data,
0,sizeof(data)); } void Dij() { for(int i=1;i<=n+2;i++) d[i]=10000000000000LL; d[begins]=0; priority_queue<pair<long long,long long> > heap; heap.push(make_pair(-d[begins],begins)); while (1){ for (;!heap.empty() && -d[heap.top().second]!=heap.top().first;heap.pop());
if (heap.empty()) break; int now=heap.top().second; heap.pop(); for (int i=head[now];i;i=nxt[i]){ int j=node[i]; if (d[j]>d[now]+data[i]){ d[j]=d[now]+data[i]; heap.push(make_pair(-d[j],j)); } } } } int main() { int t; scanf("%d",&t); int id=0; while(t--) { memset(vis,0,sizeof(vis)); id++; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%lld",&s[i].u,&s[i].v,&s[i].w); } int k; scanf("%d",&k); for(int i=1;i<=k;i++) { int x; scanf("%d",&x); vis[x]=1; } int num=1; long long ans=100000000000000LL; while(num!=20) { inist(); for(int i=1;i<=m;i++) { int u=s[i].u,v=s[i].v; if(vis[u]) { if(u&(1<<(num-1))) { u=n+1; } else u=n+2; } if(vis[v]) { if(v&(1<<(num-1))) { v=n+1; } else v=n+2; } add(u,v,s[i].w); } //begins=n+1; // Dij(); //ans=min(ans,d[n+2]); begins=n+2; Dij(); ans=min(ans,d[n+1]); num++; } printf("Case #%d: ",id); printf("%lld\n",ans); } }

HDU 6166 二進制劃分集合