这个专题主要就是学会prim和kruskal算法,另外图论最重要的就是要会建图。
J - Borg Maze
这题一开始没看懂题意,看懂之后就知道是最小生成树了,所以先bfs算出每个A和S到其他点的距离,然后求最小生成树就行了,不过最后wa了好多发。。
while (!Q.empty())
{
node u = Q.front();Q.pop();
for (int i = 0;i < num;i++)if(i!=theid)
{
if (u.x == nodes[i].x&&u.y == nodes[i].y)
{
addedge(theid, i, u.d);
nownum++;
break;
}
}
if (nownum == num)break;
if (vis[u.x][u.y])continue;
vis[u.x][u.y] = 1;
for (int i = 0;i < 4;i++)
{
int tmpx = u.x + dir[i][0];
int tmpy = u.y + dir[i][1];
if (tmpx < 0 || tmpx >= X || tmpy < 0 || tmpy >= Y)continue;
if (Map[tmpx][tmpy] == '#')continue;
if (vis[tmpx][tmpy] == 0)
{
Q.push(node(tmpx, tmpy, u.d + 1));
}
}
}
这是bfs部分,大家可以看到我加了一个剪枝,当nownum==num时就直接break,num是A和S的总个数,nownum是已经找到的个数。然而就是因为这个wa到怀疑人生。。原因是我加错地方了,因为他每个点是先判断是不是S或A,再看vis[u.x][u.y]是不是等于1,所以即是到了之前到过的点,它的nownum也会加。所以只要把这句话提到前面就行了。
当然不加也可以。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 500;
inline char read()
{
char c = getchar();
while (c == '\n')c = getchar();
return c;
/*while (c < '0' || c > '9') { if (c == '-')f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x*f;*/
}
struct Edge
{
int from, to, dist;
Edge(int _f,int _t,int _d):from(_f),to(_t),dist(_d){}
Edge(){}
bool operator<(const Edge &e)const
{
return dist > e.dist;
}
};
vector G[maxn];
char Map[maxn][maxn];
void addedge(int u, int v, int dis)
{
G[u].push_back(Edge(u, v, dis));
}
struct node
{
int x, y, d;
node(int _x,int _y,int _d):x(_x),y(_y),d(_d){}
node(){}
}nodes[maxn];
int num;
bool vis[maxn][maxn];
int dir[4][2] = { -1,0,1,0,0,-1,0,1 };
int X, Y;
void bfs(int x, int y,int theidx)
{
memset(vis, 0, sizeof(vis));
int theid = theidx;
queue Q;
Q.push(node(x,y,0));
int nownum = 0;
while (!Q.empty())
{
node u = Q.front();Q.pop();
for (int i = 0;i < num;i++)if(i!=theid)
{
if (u.x == nodes[i].x&&u.y == nodes[i].y)
{
addedge(theid, i, u.d);
nownum++;
break;
}
}
//if (nownum == num)break;
if (vis[u.x][u.y])continue;
vis[u.x][u.y] = 1;
for (int i = 0;i < 4;i++)
{
int tmpx = u.x + dir[i][0];
int tmpy = u.y + dir[i][1];
if (tmpx < 0 || tmpx >= X || tmpy < 0 || tmpy >= Y)continue;
if (Map[tmpx][tmpy] == '#')continue;
if (vis[tmpx][tmpy] == 0)
{
Q.push(node(tmpx, tmpy, u.d + 1));
}
}
}
}
bool vis1[maxn];
int prim()
{
memset(vis1, 0, sizeof(vis1));
priority_queueQ;
vis1[0] = 1;
for (int i = 0;i < G[0].size();i++)
Q.push(G[0][i]);
int edgenum = num - 1;
int ans = 0;
while (!Q.empty()&&edgenum)
{
Edge e = Q.top();Q.pop();
if (vis1[e.to])continue;
ans += e.dist;
edgenum--;
vis1[e.to] = 1;
for (int i = 0;i < G[e.to].size();i++)
{
Edge tmp = G[e.to][i];
if (!vis1[tmp.to])
Q.push(tmp);
}
}
return ans;
}
int main()
{
int T;
char b[100];
gets(b);
sscanf(b,"%d", &T);
while (T--)
{
num = 1;
for (int i = 0;i < maxn;i++)G[i].clear();
gets(b);
sscanf(b,"%d %d", &Y, &X);
//read();
for (int i = 0;i < X;i++)
{
gets(Map[i]);
for (int j = 0;j < Y;j++)
if (Map[i][j] == 'A')
{
nodes[num++] = node(i, j, 0);
}
else if (Map[i][j] == 'S')
nodes[0] = node(i, j, 0);
}
for (int i = 0;i int ans = prim();
printf("%d\n", ans);
}
return 0;
}
K - The Unique MST
判断次小生成树和最小生成树是否一样,博主不会写次小生成树。。所以我们可以先求最小生成树,然后删掉最小生成树的某些边,再跑一次kruskal看权值是不是和以前一样就行了。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 105;
const int maxm = 10005;
struct Edge
{
int from, to, dist;
int flag; // if it has been deleted
bool flag2;// if it has equal edge
Edge(int _f, int _t, int _d) :from(_f), to(_t), dist(_d) { flag = 0, flag2 = 0; }
Edge(){}
}edges[maxm];
int n, m;
int f[maxn];
int find(int a) { return f[a] == a ? a : f[a] = find(f[a]); }
int e[maxm];
map<int,int>S;
bool cmp(int a, int b)
{
return edges[a].dist < edges[b].dist;
}
vector<int>con;
int Kruskal(int times)
{
for (int i = 1;i <= n;i++)f[i] = i;
for (int i = 1;i <= m;i++)e[i] = i;
sort(e+1, e + m+1, cmp);
int u, v, rootu, rootv, dis;
int num = 0, ans = 0;
for (int i = 1;i <= m;i++)
{
int idx = e[i];
if (edges[idx].flag)continue;
u = edges[idx].from, v = edges[idx].to, dis = edges[idx].dist;
rootu = find(u), rootv = find(v);
if (rootu != rootv) { f[rootu] = rootv; ans += dis, num++;if (times == 0)con.push_back(idx); }
}
if (num != n - 1)return -1;
return ans;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
con.clear();
S.clear();
scanf("%d %d", &n, &m);
int u, v, dist;
for (int i = 1;i <= m;i++)
{
scanf("%d %d %d", &u, &v, &dist);
edges[i] = Edge(u, v, dist);
S[dist]++;
}
for (int i = 1;i <= m;i++)
if (S[edges[i].dist]>1)
edges[i].flag2 = 1;
int before=Kruskal(0);
int Size = con.size();
bool flag = true;
for (int i = 0;i < Size;i++)
{
int idx = con[i];
if (edges[idx].flag2)
{
edges[idx].flag = 1;
int tmp = Kruskal(1);
if (tmp == -1)continue;
if (tmp == before)
{
flag = false;
break;
}
edges[idx].flag = 0;
}
}
if (flag)cout << before << endl;
else puts("Not Unique!");
}
return 0;
}
近期目标:熟悉模板,争取1A!