您的位置:首页 > 大数据 > 人工智能

2018 BUPT Winter Training #8 Div.2

2018-03-07 23:11 225 查看

A - 无向图最小生成树

表白月加大佬,真是体贴萌新(笑)

最小生成树模板(话说是不是和之前树专题撞题了..)

#include <cstdio>
#include <vector>
#include <queue>
#include <utility>
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define
15d0c
PB push_back
#define MP make_pair
#define sec second
#define fir first
using namespace std;
typedef pair<int,int> pii;
vector<pii> E[1005];
bool vis[1005]={0};
priority_queue<pii,vector<pii>,greater<pii> >q;
pii tem;
int main(){
int N,M,u,v,val;
scanf("%d%d",&N,&M);
for(int i=0;i<M;i++){
scanf("%d%d%d",&u,&v,&val);
E[u].PB(MP(val,v));E[v].PB(MP(val,u));
}
int ans=0;
q.push(MP(0,1));
while(!q.empty()){
tem=q.top();q.pop();
if(vis[tem.sec])continue;
vis[tem.sec]=1;
ans+=tem.fir;
TRV(i,E[tem.sec]){
if(!vis[E[tem.sec][i].sec])q.push(E[tem.sec][i]);
}
}
printf("%d",ans);
}


B - Arbitrage

单源最短路径判正反馈环。

#include <iostream>
#include <cstring>
#include <string>
#include <map>
#include <vector>
#include <utility>
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define PB push_back
#define MP make_pair
#define sec second
#define fir first
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
using namespace std;
string name,na2;
map<string,int> currName;
struct edge{
int u,v;
double w;
edge(){}
edge(int _u,int _v,double _w){u=_u;v=_v;w=_w;}
};
vector<edge> E;
int Esize,n;
double dist[35];
bool bellman_ford(int start){
bool released=0;
memset(dist,0,sizeof(dist));
dist[start]=1;
FF(i,2,n){
released=0;
F(j,Esize){
if(dist[E[j].v]<dist[E[j].u]*E[j].w){
dist[E[j].v]=dist[E[j].u]*E[j].w;
released=1;
}
}
if(!released)return 0;
}
F(j,Esize)if(dist[E[j].v]<dist[E[j].u]*E[j].w)return 1;
return 0;
}
int main(){
int id1,id2,cas=1;
double w;
bool ZhuanDaRe;
ios::sync_with_stdio(false);
while(cin>>n){
if(!n)break;
E.clear();
ZhuanDaRe=0;
FF(i,1,n){cin>>name;currName[name]=i;}
cin>>Esize;
F(i,Esize){
cin>>name>>w>>na2;
E.PB(edge(currName[name],currName[na2],w));
}
FF(i,1,n)if(ZhuanDaRe|=bellman_ford(i))break;
cout<<"Case "<<cas++<<": "<<(ZhuanDaRe?"Yes":"No")<<endl;
}
}


C - Starry Night

(敲黑板)自创hash函数(可把我牛逼坏了?虽然前面还有几位大佬比我用的内存更少,太牛逼了!)这个hash函数的特点是可以使得直角旋转变换的相同图片拥有相同的hash值。

hash(G)=∑p∈G(pxpy(maxx−px)(maxy−py)+hash_prime)hash(G)=∑p∈G(pxpy(maxx−px)(maxy−py)+hash_prime)

#include <cstdio>
#include <map>
#include <queue>
#include <vector>
#include <cstring>
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define PB push_back
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
#define MP make_pair
#define sec second
#define fir first
using namespace std;
typedef pair<int,int> pii;
int wayx[]={-1,-1,-1,0,0,1,1,1},wayy[]={-1,0,1,-1,1,-1,0,1};
char star[105][105];
int R,C,minx,miny,maxx,maxy,cluster=1;
vector<pii> E;
void dfsgetE(int y,int x){
star[y][x]='0';
E.PB(MP(y,x));
if(minx>x)minx=x;
if(miny>y)miny=y;
if(maxx<x)maxx=x;
if(maxy<y)maxy=y;
int tx,ty;
F(i,8){
tx=wayx[i]+x;ty=wayy[i]+y;
if(tx&&ty&&tx<=C&&ty<=R){
if(star[ty][tx]=='1')dfsgetE(ty,tx);
}
}
}
map<unsigned int,int> hashmap;
void work(int y,int x){
maxx=maxy=-1;minx=C+1,miny=R+1;
E.clear();
dfsgetE(y,x);
minx--;miny--;
maxx-=minx;maxy-=miny;
maxx++;maxy++;
unsigned int hash=0;
TRV(i,E){
y=E[i].fir-miny;x=E[i].sec-minx;
hash+=233+(maxx-x)*(maxy-y)*x*y;
}
if(!hashmap[hash])hashmap[hash]=cluster++;
x=hashmap[hash];
TRV(i,E)star[E[i].fir][E[i].sec]=x-1+'a';
}
int main(){
memset(star,0,sizeof(star));
scanf("%d%d",&C,&R);
FF(i,1,R)scanf("%s",star[i]+1);
FF(i,1,R){         //y ,x
FF(j,1,C)if(star[i][j]=='1')work(i,j);
}
FF(i,1,R)printf("%s\n",star[i]+1);
}


D - 迷宫游戏

最小生成树的扩展,cmp函数变化一下而已。

#include <cstdio>
#include <cstring>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
#define MO 1061109567
using namespace std;
const int N = 505;
int t

,w
,dist
,score
={0};
bool vis
={0};
int main(){
int n,m,s,e,u,v;
memset(t,0x3f,sizeof(t));
memset(dist,0x3f,sizeof(dist));
scanf("%d%d%d%d",&n,&m,&s,&e);
F(i,n)scanf("%d",&w[i]);
F(i,m){
scanf("%d%d",&u,&v);
scanf("%d",&t[u][v]);
t[v][u]=t[u][v];
}

dist[s]=0;score[s]=w[s];
int min,mini;
F(i,n){
min=MO;
F(j,n)if(!vis[j]&&min>dist[j])min=dist[mini=j];
vis[mini]=1;
F(j,n){
if(dist[mini]+t[mini][j]<dist[j]||dist[mini]+t[mini][j]==dist[j]&&score[mini]+w[j]>score[j]){
dist[j]=dist[mini]+t[mini][j];
score[j]=score[mini]+w[j];
}
}
}
printf("%d %d",dist[e>>>>>>
,score[e]);
}


E - 贫富差距

若图不连通,直接wrong,然后就是求最近距离了

#include <iostream>
#include <cstring>
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
#define MO 1061109567
using namespace std;
const int N = 50;
int dist[N+5][N+5],n;
const int DS_size=N;
int pre[DS_size+5];
int siz[DS_size+5];
inline void init(int n){
for(int i=1;i<=n;i++)siz[pre[i]=i]=1;
}
inline int find(int x){
return x==pre[x]?x:pre[x]=find(pre[x]);
}
inline int size(int x){
return siz[find(x)];
}
void uni(int x,int y){
dist[x][y]=1;
if((x=find(x))!=(y=find(y))){
if(siz[x]>siz[y])siz[pre[y]=x]+=siz[y];
else siz[pre[x]=y]+=siz[x];
}
}
int main(){
int T,d,ans;char c;
ios::sync_with_stdio(false);
for(cin>>T;T--;){
memset(dist,0x3f,sizeof(dist));
cin>>n>>d;
FF(i,1,n)dist[i][i]=0;
init(n);
FF(i,1,n)FF(j,1,n){
cin>>c;
if(c=='Y')uni(i,j);
}
if(size(1)<n){
cout<<-1<<endl;
continue;
}
FF(k,1,n)FF(i,1,n)FF(j,1,n){
if(dist[i][j]>dist[i][k]+dist[k][j])
dist[i][j]=dist[i][k]+dist[k][j];
}
ans=0;
FF(i,1,n)FF(j,1,n){
if(dist[i][j]!=MO&&ans<dist[i][j])ans=dist[i][j];
}
cout<<ans*d<<endl;
}
}


F - 畅通工程续

最小生成树模板题。

#include <iostream>
#include <cstring>
#include <vector>
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define PB push_back
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
#define MO 1061109567
using namespace std;
struct edge{
int u,v,w;
edge(){}
edge(int _u,int _v,int _w){u=_u;v=_v;w=_w;}
};
vector<edge> E;
int n,m;
int dist[205];
bool bellman_ford(int start){
bool released=0;
memset(dist,0x3f,sizeof(dist));
dist[start]=0;
FF(i,2,n){
released=0;
F(j,m){
if(dist[E[j].v]>dist[E[j].u]+E[j].w){
dist[E[j].v]=dist[E[j].u]+E[j].w;
released=1;
}
}
if(!released)return 0;
}
//F(j,m)if(dist[E[j].v]<dist[E[j].u]*E[j].w)return 1;
return 0;
}
int main(){
int u,v,w;
ios::sync_with_stdio(false);
while(cin>>n>>m){
E.clear();
F(i,m){
cin>>u>>v>>w;
E.PB(edge(u,v,w));
E.PB(edge(v,u,w));
}
m<<=1;
cin>>u>>v;
bellman_ford(u);
cout<<(dist[v]==MO?-1:dist[v])<<endl;
}
}


G - 2条不相交的路径

考虑到Query的规模到达1e5,要用tarjan算法离线判断双连通分量

#include <cstdio>
#include <cstring>
#include <vector>
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
#define PB push_back
using namespace std;

const int N=50000;
vector<int> E[N+5];
int dfsc,Tarjan_top,Cir;
int low[N+5],dfn[N+5];
int Tarjan_stack[N+5],preCir[N+5];
bool Tarjan_ins[N+5];
void init(int n){
dfsc=1;
Tarjan_top=Cir=0;
memset(Tarjan_ins,0,sizeof(Tarjan_ins));
memset(low,0,sizeof(low));
memset(preCir,0,sizeof(preCir));
memset(dfn,0,sizeof(dfn));
FF(i,1,n)E[i].clear();
}
void Tarjan(int u,int last){
int v;
Tarjan_ins[Tarjan_stack[Tarjan_top++]=u]=1;
low[u]=dfn[u]=dfsc++;
TRV(i,E[u]){
v=E[u][i];
if(!dfn[v]){
Tarjan(v,u);
if(low[v]<low[u])low[u]=low[v];
}else if(v!=last&&Tarjan_ins[v]&&dfn[v]<low[u])low[u]=dfn[v];
}
if(dfn[u]==low[u]){
Cir++;
do{
preCir[v=Tarjan_stack[--Tarjan_top]]=Cir;
Tarjan_ins[v]=0;
}while(Tarjan_top>0&&v!=u);
}
}
int main(){
int m,n,u,v;
init(n);
scanf("%d%d",&m,&n);
F(i,n){
scanf("%d%d",&u,&v);
E[u].PB(v);E[v].PB(u);
}
FF(i,1,n)if(!dfn[i])Tarjan(i,-1);
int Q;
scanf("%d",&Q);
F(q,Q){
scanf("%d%d",&u,&v);
puts((preCir[u]==preCir[v])?"Yes":"No");
}
}


H - 天气晴朗的魔法

求最小生成树最大边权下的最大生成树。

#include <cstdio>
#include <vector>
#include <algorithm>
#define INTMAX 0x7fffffff
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define all(x) x.begin(),x.end()
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define FF(_i,_l,_r) for(int _i=_l;_i<=(_r);_i++)
#define FS(_i,_r,_l) for(int _i=_r;_i>=(_l);_i--)
#define PB push_back
using namespace std;
struct edge{
int u,v;
int w;
edge(){}
edge(int _u,int _v,int _w){u=_u;v=_v;w=_w;}
};
const int N=100000;
vector<edge> E;
bool vis[N+5]={0};
bool cmp(edge x,edge y){
return x.w>y.w;
}
const int DS_size=N;
int pre[DS_size+5];
int siz[DS_size+5];
inline void init(int n){
for(int i=1;i<=n;i++)siz[pre[i]=i]=1;
}
inline int find(int x){
return x==pre[x]?x:pre[x]=find(pre[x]);
}
inline int size(int x){
return siz[find(x)];
}
bool uni(int x,int y){
if((x=find(x))!=(y=find(y))){
if(siz[x]>siz[y])siz[pre[y]=x]+=siz[y];
else siz[pre[x]=y]+=siz[x];
return 1;
}
return 0;
}
int main(){
int N,M,u,v,val;
scanf("%d%d",&N,&M);
init(N);
for(int i=0;i<M;i++){
scanf("%d%d%d",&u,&v,&val);
E.PB(edge(u,v,val));
}
sort(all(E),cmp);
int maxw=-INTMAX;
long long ans=0;
TRV(i,E){
if(uni(E[i].u,E[i].v)&&maxw<E[i].w)maxw=E[i].w;
}
init(N);
F(i,M){
if(E[i].w>maxw)continue;
if(uni(E[i].u,E[i].v))ans+=E[i].w;
}
printf("%lld",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: