都存于小组成员练习题中
数据结构实验:连通分量个数
主要运用并查集的相关知识(不懂的可以学习一下)
#include
#include
#include
#include
using namespace std;
int b[1000];
int find(int x)
{
while ( b[x] != x )
x = b[x];
return x;
}
void meget(int x, int y)
{
int fx = find(x);
int fy = find(y);
if ( b[fx] != fy )
b[fx] = fy;
}
int main()
{
int T;
int n, m, i, j;
scanf ( "%d", &T );
while ( T-- )
{
int h, h1;
scanf ( "%d %d", &n, &m );
for ( i = 1;i <= n; i++ )
b[i] = i;
for ( i = 0;i < m; i++ )
{
scanf ( "%d %d", &h, &h1 );
meget(h, h1);
}
int sum = 0;
for ( i = 1;i <= n; i++ )
{
if ( b[i] == i )
sum++;
}
printf ( "%d\n", sum );
}
return 0;
}
顾名思义运用深搜
#include
#include
#include
#include
using namespace std;
bool ma[105][105];
bool vis[105];
int n, m;
void dfs(int x)
{
int i;
for ( i = 0;i < n; i++ )
{
if ( !vis[i] && ma[x][i] )
{
printf ( " %d", i );
vis[i] = true;
dfs(i);
}
}
}
int main()
{
int x, y;
int i, T;
scanf ( "%d", &T );
while ( T-- )
{
memset( ma, false, sizeof(ma) );
memset( vis, false, sizeof(vis) );
scanf ( "%d %d", &n, &m );
for ( i = 0; i < m; i++ )
{
scanf ( "%d %d", &x, &y );
ma[x][y] = true;
ma[y][x] = true;
}
vis[0] = true;
printf ( "0" );
dfs(0);
printf ( "\n" );
}
return 0;
}
还是并查集
#include
#include
#include
#include
using namespace std;
int b[1000];
int find(int x)
{
while ( b[x] != x )
x = b[x];
return x;
}
void meget(int x, int y)
{
int fx = find(x);
int fy = find(y);
if ( b[fx] != fy )
b[fx] = fy;
}
int main()
{
int n, m, i, j;
while ( ~scanf ( "%d %d", &n, &m ) )
{
int h, h1;
for ( i = 1;i <= n; i++ )
b[i] = i;
for ( i = 0;i < m; i++ )
{
scanf ( "%d %d", &h, &h1 );
meget(h, h1);
}
int sum = 0;
for ( i = 1;i <= n; i++ )
{
if ( b[i] == i )
sum++;
}
printf ( "%d\n", sum );
}
return 0;
}
主要运用广搜
#include
#include
#include
#include
#include
using namespace std;
int k;
bool vis[102];
bool ma[102][102];
void bfs(int x)
{
int i;
bool ok = false;
queue q;
q.push(x);
vis[x] = true;
while ( !q.empty() )
{
int temp = q.front();
if ( !ok )
{
ok = !ok;
printf ( "%d", temp );
}
else
printf ( " %d", temp );
q.pop();
for ( i = 0;i < k; i++ )
{
if ( ma[temp][i]&&!vis[i] )
{
q.push(i);
vis[i] = true;
}
}
}
}
int main()
{
int t, m, i;
int T;
int x, y;
scanf ( "%d", &T );
while ( T-- )
{
memset( ma, false, sizeof(ma) );
memset ( vis, false, sizeof(vis) );
scanf ( "%d %d %d", &k, &m, &t );
for ( i = 0;i < m; i++ )
{
scanf ( "%d %d", &x, &y );
ma[x][y] = true;
ma[y][x] = true;
}
bfs(t);
printf ( "\n" );
}
return 0;
}
还是广搜
#include
#include
#include
#include
#include
using namespace std;
int n, m, t;
bool vis[105], book[105][105];
void bfs(int t)
{
int i;
queue q;
q.push(t);
vis[t] = true;
while ( !q.empty() )
{
int temp = q.front();
q.pop();
for ( i = 0;i < n; i++ )
{
if ( !vis[i]&&book[temp][i] )
{
printf ( " %d", i );
q.push(i);
vis[i] = true;
}
}
}
}
int main()
{
int T;
int i, j;
int x, y;
scanf ( "%d", &T );
while ( T-- )
{
memset ( vis, false, sizeof(vis) );
memset ( book, false, sizeof(book) );
scanf ( "%d %d %d", &n, &m, &t );
for ( i = 0;i < m; i++ )
{
scanf ( "%d %d", &x, &y );
book[x][y] = true;
book[y][x] = true;
}
printf ( "%d", t );
bfs(t);
}
}
这个题可能是我花费时间最长的题了吧!还是技术不行啊!
这个题你想用AOE麻烦死你,想用最短路(寻找最长路)的方法你也要选对了方式要不就超时了!
所以根本不能用Dijkstra算法、Bellman-Ford算法更别想用三层循环的Floyd-Warshall算法了!
因为以上算法我都试过都超时了。。。。所以就只能用优化队列形式的Bellman-Ford算法(SPEA)
这里要记下前驱所以我们要从终点到起点建立一个联系存最长路经过的点(这里我用的是book[])。
#include
#include
#include
#include
#include
using namespace std;
const int N = 50010;
const int inf = (1<<20);
struct node
{
int dist;
int to;
int next;
}E[3*N];
int top, xx, yy, n, m;
bool bookx[N], booky[N], vis[N];
int head[N], dis[N], book[N];
void init()
{
int i;
for ( i = 1;i <= n; i++ )
book[i] = inf;
memset ( head, -1, sizeof(head) );
memset ( bookx, false, sizeof(bookx) );
memset ( booky, false, sizeof(booky) );
top = 0;
}
void Point()
{
int i;
for ( i = 1;i <= n; i++ )
{
if ( !bookx[i] )
xx = i;
if ( !booky[i] )
yy = i;
}
}
void SPEA()
{
int i;
for ( i = 1;i <= n; i++ )
{
dis[i] = inf;
vis[i] = false;
}
vis[yy] = true;
dis[yy] = 0;
queue q;
q.push(yy);
while ( !q.empty() )
{
int u = q.front();
q.pop();
vis[u] = false;
for ( i = head[u];i != -1; i = E[i].next )
{
int v = E[i].to;
if ( dis[v] >= inf||dis[v] < dis[u]+E[i].dist )
{
dis[v] = dis[u]+E[i].dist;
book[v] = u;
if ( !vis[v] )
{
vis[v] = true;
q.push(v);
}
}
else if ( dis[v] == dis[u]+E[i].dist&&book[v] > u )
book[v] = u;
}
}
}
int main()
{
int i, j;
int u, v, dist;
while ( ~scanf ( "%d %d", &n, &m ) )
{
init();
for ( i = 0;i < m; i++ )
{
scanf ( "%d %d %d", &u, &v, &dist );
booky[u] = true;
bookx[v] = true;
E[top].to = u;
E[top].dist = dist;
E[top].next = head[v];
head[v] = top++;
}
Point();
SPEA();
printf ( "%d\n", dis[xx] );
i = xx;
while ( i != yy )
{
printf ( "%d %d\n", i, book[i] );
i = book[i];
}
}
return 0;
}
用深搜的方式
#include
#include
#include
#include
#include
using namespace std;
int n;
bool vis[1002];
bool ma[1002][1002];
int book[1002];
int sum;
void dfs(int x)
{
int i;
book[sum++] = x;
vis[x] = true;
for ( i = 1;i <= n; i++ )
{
if ( !vis[i]&&ma[x][i] )
{
dfs(i);
book[sum++] = x;
}
}
}
int main()
{
int T, s;
int x, y;
int m, i;
scanf ( "%d", &T );
while ( T-- )
{
sum = 0;
memset( ma, false, sizeof(ma) );
memset( vis, false, sizeof(vis) );
scanf ( "%d %d %d", &n, &m, &s );
for ( i = 0;i < m; i++ )
{
scanf ( "%d %d", &x, &y );
ma[x][y] = true;
ma[y][x] = true;
}
dfs(s);
if ( sum == n*2-1 )
{
for ( i = 0; i < sum; i++ )
{
printf ( i != sum-1 ? "%d " : "%d\n", book[i] );
}
}
else
{
for ( i = 0; i < sum; i++ )
{
printf ( "%d ", book[i] );
}
printf ( "0\n" );
}
}
return 0;
}
最小生成树
#include
#include
#include
#include
using namespace std;
struct node
{
int x;
int y;
int dis;
};
int b[1002];
bool cmp ( node q, node p )
{
return q.dis < p.dis;
}
int find( int x )
{
while ( b[x] != x )
x = b[x];
return x;
}
bool meget( int x, int y )
{
int fx = find(x);
int fy = find(y);
if ( fx != fy )
{
b[fx] = fy;
return true;
}
return false;
}
int main()
{
int n, m, i;
while ( ~scanf ( "%d %d", &n, &m ) )
{
node a[6002];
for ( i = 1;i <= n; i++ )
b[i] = i;
for ( i = 0;i < 2*m; i++ )
{
scanf ( "%d %d %d", &a[i].x, &a[i].y, &a[i].dis );
a[i+1].x = a[i].y;
a[i+1].y = a[i].x;
a[i+1].dis = a[i].dis;
i++;
}
sort ( a, a+2*m, cmp );
int sum = 0;
int cnt = 0;
for ( i = 0;i < 2*m; i++ )
{
if ( meget(a[i].x, a[i].y) )
{
cnt++;
sum = sum+a[i].dis;
if ( cnt == n-1 )
break;
}
}
if ( cnt == n-1 )
printf ( "%d\n", sum );
else
printf ( "-1\n" );
}
return 0;
}
数据结构实验之图论七:驴友计划
Bell-Ford算法(主要改变是要用两个更新数组一个是距离dis[], 一个是钱数book[])
#include
#include
#include
#include
using namespace std;
const int inf = (1<<30);
struct node
{
int x, y;
int spend, len;
}a[400000];
int book[600];
int dis[600];
int main()
{
int T, i, j;
int n, m, x, y;
scanf ( "%d", &T );
while ( T-- )
{
scanf ( "%d %d %d %d", &n, &m, &x, &y );
memset( book, 0, sizeof(book) );
for ( i = 0;i < 2*m; i++ )
{
scanf ( "%d %d %d %d", &a[i].x, &a[i].y, &a[i].len, &a[i].spend );
i++;
a[i].x = a[i-1].y;
a[i].y = a[i-1].x;
a[i].spend = a[i-1].spend;
a[i].len = a[i-1].len;
}
for ( i = 0;i < n; i++ )
dis[i] = inf;
dis[x] = 0;
int sum = 0;
for ( i = 0;i < n-1; i++ )
{
for ( j = 0;j < 2*m; j++ )
{
if ( dis[a[j].y] > dis[a[j].x]+a[j].len )
{
dis[a[j].y] = dis[a[j].x]+a[j].len;
book[a[j].y] = book[a[j].x]+a[j].spend;
}
else if ( dis[a[j].y] == dis[a[j].x]+a[j].len&&book[a[j].x]+a[j].spend < book[a[j].y] )
{
book[a[j].y] = book[a[j].x]+a[j].spend;
}
}
}
printf ( "%d %d\n", dis[y], book[y] );
}
return 0;
}
在做这题之前我们首先要复习一下生成欧拉回路所需要的条件
判断欧拉回路是否存在的方法
有向图:图连通,所有的顶点出度=入度。且没有孤立点(没有入度出度是0的点)
无向图:图连通,所有顶点都是偶数度。且没有孤立点(没有入度出度是0的点)
这题很明显就是无向图
我们就要判断有没有点被孤立了,是不是都是偶数度,是不是图联通(这个要用我们学到的并查集)
#include
#include
#include
#include
using namespace std;
bool a[1005][1005];
int du[1005];
int book[1005];
int find(int x)
{
while ( book[x] != x )
x = book[x];
return x;
}
void meget(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
{
book[fx] = fy;
}
}
int main()
{
int T;
int x, y;
int n, m, i;
scanf ( "%d", &T );
while ( T-- )
{
memset( a, false, sizeof(a) );
memset( du, 0, sizeof(du) );
scanf ( "%d %d", &n, &m );
for ( i = 1;i <= n; i++ )
book[i] = i;
for ( i = 1;i <= m; i++ )
{
scanf ( "%d %d", &x, &y );
if ( !a[x][y] )
{
a[x][y] = a[y][x] = true;
du[x]++;
du[y]++;
}
meget(x, y);
}
int temp = 0;
int sum = 0;
for ( i = 1;i <= n; i++ )
{
if ( book[i] == i )
sum++;
if ( du[i]%2 != 0 )
{
temp = 2;
break;
}
}
if ( sum == 1&&temp == 0 )
printf ( "1\n" );
else
printf ( "0\n" );
}
}
如有帮助记得支持我一下,谢谢!!!