Anda di halaman 1dari 8

#include <stdio.

h>
#include <alloc.h>
#define MAXN 100
typedef struct
{
int n;
int a[MAXN][MAXN];
}matrice;
typedef struct sEem {
int n;
int e[MAXN][2];
int p;
int ep[2];
} Eem;
typedef struct sciclu {
int a[MAXN];
struct sciclu *next;
} ciclu;
typedef struct sbest {
ciclu *solutii;
int n;
int best;
} best;
int CitireSimetrica(matrice *a)
{
int i,j;
printf("n=");
scanf("%d",&a->n);
for(i=0;i<a->n;i++){
for(j=i;j<a->n;j++){
{
printf("a[%d][%d]=",j,i);
scanf("%d",&a->a[j][i]);
a->a[i][j]=a->a[j][i];
}
}
}
return(0);
}
void Tiparire(matrice *a)
{
int i,j;
for(i=0;i<a->n;i++){
for(j=0;j<a->n;j++){
if(a->a[j][i]>=0)
printf("%4d ",a->a[j][i]);
else
printf("%4c ",(-1*a->a[j][i])+'A'-1);
}
printf("\n");
}
}

void PonderiMinimale(matrice *a,matrice *b)


{
int i,j,k,p;
/* i - linie j - coloana */
b->n=a->n;
for(i=0;i<a->n;i++){
for(j=0;j<a->n;j++){
if(i!=j){
k=0;
for(p=0;p<a->n;p++)
if((p!=i)&&(a->a[p][i]<a->a[j][i]))
k++;
for(p=0;p<a->n;p++)
if((p!=j)&&(a->a[j][p]<a->a[j][i]))
k++;
b->a[i][j]=k;
}else{
b->a[i][j]=-1;
}
}
}
}
int minim(int *a, int p, int n, int *v)
{
int i, j;
for (i = 0; i < n; i++) {
if ((i != p) && (v[i])) {
j = i;
}
}
for (i = 0; i < n; i++) {
if ((i != p) && (v[i]) && (a[j] > a[i])) {
j = i;
}
}
return (a[j]);
}
void Rezolvare7(matrice * a, Eem * b)
{
int n, an;
int s[MAXN], v[MAXN], i, j, max, k, p;
b->n = 0;
b->p = -1;
n = a->n;
/* initializare v
for (i = 0; i
v[i] = 1;
s[i] = 0;
for (j = 0;
s[i] +=
}

si s */
< n; i++) {
j < n; j++) {
a->a[i][j];

}
an = n;
/* cat timp nu avem mai mic decat 3 repetam pasii */
while (an >= 3) {
/* aflam maximul din s */
max = s[0];
for (i = 1; i < n; i++) {
if (max < s[i]) {
max = s[i];
}
}
/* cautam acum toti maximii din s */
for (i = 0; i < n; i++) {
/* am gasit un maxim */
if (s[i] == max) {
/* aflam minimul de pe linia i */
j = minim(a->a[i], i, n, v);
/* luam toate minimele posibile */
for (k = 0; k < n; k++) {
/* am gasit un minim */
if ((v[k]) && (a->a[i][k] == j)) {
/* am aflat element esential minimal (i,k) */
b->e[b->n][0] = i;
b->e[b->n++][1] = k;
/* verificam sa nu existe suprapuneri */
v[i] = 0;
an--;
s[i] = 0;
v[k] = 0;
an--;
s[k] = 0;
/* aplicam formula de s=s-aik-ajk */
for (p = 0; p < n; p++) {
if (p == i) {
continue;
}
if (p == k) {
continue;
}
s[p] = s[p] - a->a[i][p] - a->a[k][p];
}
#ifdef NU_TOATE_MINIMELE
break;
#endif
}
}
}
}
}
/* verificam in care din cazurile n=1,2 suntem */
switch (an) {
case 2:
b->p = 0;
j = 0;
for (i = 0; i < n; i++) {

if (v[i]) {
v[i] = 0;
b->ep[b->p++] = i;
if (!j) {
j = 1;
} else {
break;
}
}
}
break;
case 1:
b->p = 0;
for (i = 0; i < n; i++) {
if (v[i]) {
b->ep[b->p++] = i;
break;
}
}
break;
default:
/* nu se poate ajunge aici (teoretic :) */
break;
}
}
void PrintEem(Eem * e, const char *s)
{
int i;
printf("%s", s);
for (i = 0; i < e->n; i++) {
printf("(%d,%d)", e->e[i][0] + 1, e->e[i][1] + 1);
}
printf("\n");
switch (e->p) {
case 1:
printf("%d este varf de articulatie minimala\n", e->ep[0] + 1);
break;
case 2:
printf("%d,%d este ultimul element esential minimal al"
" grafului.\n", e->ep[0] + 1, e->ep[1] + 1);
break;
default:
printf("Eroare apel afisare !\n");
break;
}
}
int valid_a(int a, int x, int b, Eem * e)
{
int i, j, k;
for (i = 0; i < e->n; i++) {
j = e->e[i][0];
k = e->e[i][1];
if ((j == x) || (k == x)) {
/* am gasit pereche Eem care-l contine pe x */
/* verificam daca (x,a) sau (x,b) == (j,k) */

if (!(
((j == x) && (k == a)) ||
((j == x) && (k == b)) ||
((k == x) && (j == a)) || ((k == x) && (j == b))
)) {
return (0);
}
break;
}
}
/* elementul x nu face parte dintr-o pereche Eem */
return (1);
}
int valid(int *b, int k, Eem * e, int n)
{
int i;
for (i = 0; i < k; i++) {
if (b[i] == b[k]) {
return (0);
}
}
for (i = 1; i < k; i++) {
if (!valid_a(b[i - 1], b[i], b[i + 1], e)) {
return (0);
}
}
if (k == n - 1) {
if (!valid_a(b[k - 1], b[k], b[0], e)) {
return (0);
}
if (!valid_a(b[k], b[0], b[1], e)) {
return (0);
}
}
return (1);
}
void AdaugaSolutie(int *b, int n, matrice * a, best * sol,int sign)
{
int i, s = 0;
ciclu *z;
for (i = 0; i < n - 1; i++) {
s += a->a[b[i]][b[i + 1]];
}
s += a->a[b[0]][b[n - 1]];
if (!((sol->solutii == NULL) || (sign * sol->best > sign * s))) {
/* nu avem o solutie mai buna decat cea(cele) existente */
return;
}
if ((sol->solutii != NULL) && (sign * sol->best > sign * s)) {
/* avem o soluti mai buna decat cele existente,deci trebuie
sa le stergem pe restul */
while (sol->solutii != NULL) {
z = sol->solutii->next;

free(sol->solutii);
sol->solutii = z;
}
}
/* acum adaugam solutia gasita */
sol->best = s;
z = (ciclu *) malloc(sizeof(ciclu));
if (z == NULL) {
printf("Nu mai pot aloca spatiu pentru solutii!\n");
return;
}
for (i = 0; i < n; i++) {
z->a[i] = b[i];
}
z->next = sol->solutii;
sol->solutii = z;
}
void Cicluri(Eem * e, int n, matrice * a,best *solutii,int sign)
{
int b[MAXN] = { 0 };
int k = 1, ok, i;
solutii->n=n;
solutii->solutii=0;
solutii->best=0;
b[0] = 0;
b[k] = -1;
while (k > 0) {
ok = 0;
while ((!ok) && (b[k] < n - 1)) {
b[k]++;
ok = valid(b, k, e, n);
}
if (ok) {
if (k == n - 1) {
AdaugaSolutie(b, n, a, solutii,sign);
/* am aflat o solutie */
} else {
b[++k] = -1;
}
} else {
k--;
}
}
}
void AfiseazaSolutii(best * sol)
{
int i;
ciclu *a;
printf("Ciclurile minimale sunt:\n");
for (a = sol->solutii; a != NULL; a = a->next) {

for (i = 0; i < sol->n; i++) {


printf("%d ", a->a[i]+1);
}
printf("%d\n", a->a[0]+1);
}
}
void MatriceaMare(matrice *a,matrice *dest)
{
int i,j,b;
b=a->a[0][0];
for(i=0;i<a->n;i++)
for(j=0;j<a->n;j++)
if(a->a[i][j]>b)
b=a->a[i][j];
dest->n=a->n;
for(i=0;i<a->n;i++)
for(j=0;j<a->n;j++)
if(i!=j)
dest->a[i][j]=b-a->a[i][j];
else
dest->a[i][j]=0;
}
int main(void)
{
matrice a,b;
Eem e;
best sol;
CitireSimetrica(&a);
PonderiMinimale(&a,&b);
printf("Matricea cu ponderi minimale:\n");
Tiparire(&b);
Rezolvare7(&b,&e);
PrintEem(&e,"Circuite minimale");
#ifndef QUIET
printf("Caut circuite minimale...\n");
#endif
Cicluri(&e,a.n, &a, &sol,1);
AfiseazaSolutii(&sol);
#ifndef QUIET
MatriceaMare(&b,&b);
printf("Matricea cu ponderi maximale:\n");
Tiparire(&b);
Rezolvare7(&b,&e);
PrintEem(&e,"Circuite minimale\n");
printf("Caut circuite minimale...\n");
Cicluri(&e,a.n, &a, &sol,1);
AfiseazaSolutii(&sol);
#endif

return(0);
}