全是憨批題的專題
可能是爲了在並查集之後給人恢復信心
簡略寫一下
1.POJ 1251 Jungle Roads
模板題,把字母轉化爲數字
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
int n,m,a[5005],ans,cnt,num;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v,w;
}e[200005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+num,cmp);
for(int i=1;i<=num;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans+=e[i].w;
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
while(cin>>n){
for(int i=1;i<=n;i++){
a[i]=i;
}
if(n==0)break;
memset(e,0,sizeof(e));
char u[5],v[5];
int t,w;
num=0,cnt=0;
ans=0;
for(int i=1;i<=n-1;i++){
scanf("%s%d",u,&t);
for(int j=1;j<=t;j++){
scanf("%s%d",v,&w);
e[++num].u=u[0]-'A'+1;
e[num].v=v[0]-'A'+1;
e[num].w=w;
}
}
krus();
cout<<ans<<endl;
}
return 0;
}
2.POJ 1287 Networking
模板題
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
int n,m,a[5005],ans,cnt,num;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v,w;
}e[200005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+m,cmp);
for(int i=1;i<=m;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans+=e[i].w;
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
while(cin>>n){
for(int i=1;i<=n;i++){
a[i]=i;
}
if(n==0)break;
memset(e,0,sizeof(e));
cin>>m;
num=0,cnt=0;
ans=0;
for(int i=1;i<=m;i++){
e[i].u=read();
e[i].v=read();
e[i].w=read();
}
krus();
cout<<ans<<endl;
}
return 0;
}
3.POJ 2031 Building a Space Station
三維歐幾里得距離,如果距離小於r1+r2則爲0,否則減去
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
int n,m,a[5005];
double ans,cnt;
int num;
double juli(double x1,double y1,double z1,double x2,double y2,double z2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
}
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct node{
double x,y,z,r;
}pos[1005];
struct edge{
int u,v;
double w;
}e[200005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+num,cmp);
for(int i=1;i<=num;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans+=e[i].w;
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
while(cin>>n){
for(int i=1;i<=n;i++){
a[i]=i;
}
if(n==0)break;
memset(e,0,sizeof(e));
num=0,cnt=0;
ans=0;
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf%lf",&pos[i].x,&pos[i].y,&pos[i].z,&pos[i].r);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
e[++num].u=i;
e[num].v=j;
double w=juli(pos[i].x,pos[i].y,pos[i].z,pos[j].x,pos[j].y,pos[j].z);
if(w<=pos[i].r+pos[j].r)w=0;
else w-=pos[i].r+pos[j].r;
e[num].w=w;
}
}
krus();
printf("%.3f\n",ans);
}
return 0;
}
4.POJ 2421 Constructing Roads
給個距離矩陣,再給已有的邊,直接把已有的加入並查集或者距離設置爲0都可
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
using namespace std;
int n,m,a[5005],ans,cnt,num;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v,w;
}e[200005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+num,cmp);
for(int i=1;i<=num;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans+=e[i].w;
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
n=read();
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int w;
w=read();
if(j>i){
e[++num].u=i;
e[num].v=j;
e[num].w=w;
}
}
}
m=read();
for(int i=1;i<=m;i++){
int x,y;
x=read(),y=read();
hb(x,y);
}
krus();
cout<<ans;
return 0;
}
5.ZOJ 1586 QS Network
邊權加上兩點點權
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
using namespace std;
int n,m,a[5005],ans,cnt,num,cost[5005];
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v,w;
}e[200005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+num,cmp);
for(int i=1;i<=num;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans+=e[i].w;
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
int t;
t=read();
while(t--){
n=read();
num=0,ans=0,cnt=0;
memset(e,0,sizeof(e));
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=1;i<=n;i++){
cost[i]=read();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int w;
w=read();
if(j>i){
e[++num].u=i;
e[num].v=j;
e[num].w=w+cost[i]+cost[j];
}
}
}
krus();
cout<<ans<<endl;
}
return 0;
}
6.POJ 1789 Truck History
兩個字符串中不同字符的數量爲權,稠密圖,適合prim,特意學了一下堆優化prim
之前對vector用memset一直MLE後來換了clear才過,才知道不能對vector和string用memset,會發生內存泄漏,記住!
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
int k,n,m,cnt,ans,sum;
int dis[2005],vis[2005];
struct edge{
int v,w;
};
struct node{
int w,now;
bool operator <(const node&x)const
{
return w>x.w;
}
};
vector<edge>g[2005];
priority_queue<node>q;
void prim(){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[1]=0;
q.push((node){0,1});
while(!q.empty()&&cnt<n){
node x=q.top();
q.pop();
int d=x.w;
int u=x.now;
if(vis[u])continue;
cnt++;
sum+=d;
vis[u]=1;
for(int i=0;i<g[u].size();i++){
if(g[u][i].w<dis[g[u][i].v]){
dis[g[u][i].v]=g[u][i].w;
q.push((node){dis[g[u][i].v],g[u][i].v});
}
}
}
while(!q.empty())q.pop();
return;
}
string a[2005];
int getd(int i,int j){
int c=0;
for(int x=0;x<7;x++){
if(a[i][x]!=a[j][x])c++;
}
return c;
}
int main(){
while(cin>>n){
if(n==0)break;
cnt=0,sum=0,ans=0;
// memset(g,0,sizeof(g));
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++)
{
int w=getd(i,j);
g[i].push_back((edge){j,w});
g[j].push_back((edge){i,w});
}
}
prim();
if(cnt==n)printf("The highest possible quality is 1/%d.\n",sum);
for(int i=1;i<=n;i++){
g[i].clear();
}
}
return 0;
}
7.POJ 2349 Arctic Network
最小生成樹的最大邊
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
int n,m,a[5005],cnt,bs=1,qq;
int dis[1005][1005];
double ans;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v;
double w;
}e[1000005];
struct node{
double x,y;
}pos[1000005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+bs,cmp);
for(int i=1;i<=bs;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans=max(ans,e[i].w);
hb(u,v);
if(++cnt==n-m)break;
}
}
int main(){
int tt;
cin>>tt;
while(tt--){
m=read(),n=read();
for(int i=1;i<=n;i++){
a[i]=i;
}
cnt=0,ans=0,bs=1;
for(int i=1;i<=n;i++){
pos[i].x=read();
pos[i].y=read();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
e[bs].u=i;
e[bs].v=j;
e[bs].w=(double)sqrt((pos[i].x-pos[j].x)*(pos[i].x-pos[j].x)+(pos[i].y-pos[j].y)*(pos[i].y-pos[j].y));
bs++;
}
}
krus();
printf("%.2f\n",ans);
}
return 0;
}
8.POJ 1751 Highways
給一些權爲0的邊,求最小生成樹中非0邊的連接的端點
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
int n,m,a[5005],cnt,bs=1,qq;
int dis[1005][1005];
double ans;
double juli(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v;
double w;
}e[1000005];
struct node{
double x,y;
}pos[1000005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+bs,cmp);
for(int i=1;i<=bs;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
if(e[i].w!=0){
printf("%d %d\n",u,v);
}
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
n=read();
for(int i=1;i<=n;i++){
a[i]=i;
}
cnt=0,ans=0,bs=1;
for(int i=1;i<=n;i++){
pos[i].x=read();
pos[i].y=read();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
e[bs].u=i;
e[bs].v=j;
e[bs].w=juli(pos[i].x,pos[i].y,pos[j].x,pos[j].y);
bs++;
}
}
m=read();
for(int i=1;i<=m;i++){
e[bs].u=read();
e[bs].v=read();
e[bs].w=0;
bs++;
}
krus();
return 0;
}
9.POJ 1258 Agri-Net
跟前面某題一樣的模板題
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
using namespace std;
int n,m,a[5005],ans,cnt,num,cost[5005];
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
struct edge{
int u,v,w;
}e[200005];
int find(int x){
if(a[x]==x)return x;
return a[x]=find(a[x]);
}
void hb(int y,int x){
a[find(y)]=find(x);
return;
}
bool cmp(edge a,edge b){
return a.w<b.w;
}
void krus(){
sort(e+1,e+1+num,cmp);
for(int i=1;i<=num;i++){
int u,v;
u=e[i].u;
v=e[i].v;
if(find(u)==find(v))continue;
ans+=e[i].w;
hb(u,v);
if(++cnt==n-1)break;
}
}
int main(){
while(cin>>n){
num=0,ans=0,cnt=0;
memset(e,0,sizeof(e));
for(int i=1;i<=n;i++){
a[i]=i;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int w;
w=read();
if(j>i){
e[++num].u=i;
e[num].v=j;
e[num].w=w;
}
}
}
krus();
cout<<ans<<endl;
}
return 0;
}
10.POJ 3026 Borg Maze
每個點都能作爲出發點,bfs每個點到其他點的距離建邊
11.POJ 1679 The Unique MST
次小生成樹模板題
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf =0x3f3f3f3f;
int n,m;
struct node{
int u,v,w;
int vis;
}e[20010];
vector<int>g[110];
int f[105],maxx[105][105];
bool cmp(node a,node b){
return a.w<b.w;
}
int find(int x){
if(f[x]==x)return x;
return f[x]=find(f[x]);
}
void krus(){
sort(e+1,e+1+m,cmp);
for(int i=0;i<=n;i++){
g[i].clear();
g[i].push_back(i);
f[i]=i;
}
int sum=0,cnt=0;
for(int i=1;i<=m;i++){
if(cnt==n-1)break;
int u=e[i].u;
int v=e[i].v;
if(find(u)==find(v))continue;
u=find(u);
v=find(v);
e[i].vis=1;
cnt++;
sum+=e[i].w;
for(int j=0;j<g[u].size();j++){
for(int k=0;k<g[v].size();k++){
maxx[g[u][j]][g[v][k]]=maxx[g[v][k]][g[u][j]]=e[i].w;
}
}
f[find(u)]=find(v);
for(int j=0;j<g[u].size();j++){
g[v].push_back(g[u][j]);
}
}
int ss=inf;
for(int i=1;i<=m;i++){
if(!e[i].vis){
ss=min(ss,sum+e[i].w-maxx[e[i].u][e[i].v]);
}
}
if(ss>sum){
printf("%d\n",sum);
}
else printf("Not Unique!\n");
}
int main(){
int t;
cin>>t;
while(t--){
cin>>n>>m;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
e[i].vis = 0;
}
krus();
}
return 0;
}
12.HDU 1233 還是暢通工程
純模板
13.HDU 1301 Jungle Roads
跟T1一樣
14.HDU 1875 暢通工程再續
跟之前給座標求距離的題一樣
這個專題很快速的搞完了
接着弄完生成樹專題,然後
六月
打算搞一整個月數論和DP,雖然以後我不負責這一塊,但是至少要會基礎內容,不然隊友卡了的時候我都不能提供思路